diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml new file mode 100644 index 0000000000..70a56cf329 --- /dev/null +++ b/.github/workflows/scala.yml @@ -0,0 +1,53 @@ +name: Build + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + services: + postgres: + image: postgres + env: + POSTGRES_DB: exam_test + POSTGRES_USER: exam + POSTGRES_PASSWORD: exam + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: temurin + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 20.x + + - name: Build UI + run: | + rm -rf node_modules + npm i + npm run check-format + npm run check-lint + npm run build + + - name: Build backend and run tests + run: | + sed -i 's/\/var\/log\/exam/logs/g' $GITHUB_WORKSPACE/conf/logback.xml + sbt test + + diff --git a/.gitignore b/.gitignore index b090d7c3ba..41c83b095b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ target default-drop-all.sql default-create-all.sql /data/ -.angular \ No newline at end of file +.angular +dist diff --git a/.scalafix.conf b/.scalafix.conf new file mode 100644 index 0000000000..787b62eb7f --- /dev/null +++ b/.scalafix.conf @@ -0,0 +1,6 @@ +rules = [DisableSyntax, OrganizeImports, RedundantSyntax] +OrganizeImports { + removeUnused = false + groupedImports = Keep + coalesceToWildcardImportThreshold = 3 +} diff --git a/.scalafmt.conf b/.scalafmt.conf index be9fecc889..3c5eb06dea 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,2 +1,4 @@ -align = more -maxColumn = 100 +version = "3.7.7" +runner.dialect = scala3 +align.preset = more +maxColumn = 120 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e446bd03f6..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -os: linux - -dist: xenial - -language: - - scala - -jdk: - - openjdk11 - -node_js: - - 18 - -services: - - postgresql - -addons: - postgresql: "9.6" - -before_script: - - psql -c "CREATE USER sitnet WITH PASSWORD 'sitnetsitnet';" -U postgres - - psql -c 'CREATE DATABASE sitnet_test WITH OWNER 'sitnet';' -U postgres - - sed -i 's/\/var\/log\/exam/logs/g' $TRAVIS_BUILD_DIR/conf/logback.xml - - rm -rf ui/node_modules - - cd ui - - npm install -script: - - npm run build - - npm run check-format - - npm run check-lint - - cd .. - - sbt test - -before_cache: - # Tricks to avoid unnecessary cache updates - - find $HOME/.sbt -name "*.lock" | xargs rm - - find $HOME/.ivy2 -name "ivydata-*.properties" | xargs rm - -cache: - directories: - - $HOME/.cache/coursier - # $HOME/.ivy2/cache - - $HOME/.sbt diff --git a/README.md b/README.md index d8d9e5d4d7..25cd0c59f4 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,36 @@ -[![Build Status](https://api.travis-ci.com/CSCfi/exam.svg?branch=master)](https://app.travis-ci.com/github/CSCfi/exam) +[![Build](https://github.com/CSCfi/exam/actions/workflows/scala.yml/badge.svg?branch=dev)](https://github.com/CSCfi/exam/actions) EXAM Quickstart for developers ===================================== -1. Prerequisites: install SBT, Java (11), Node (>= 14) and PostgreSQL (>= 9.4). +1. Prerequisites: install SBT, Java (21), Node (>= 18) and PostgreSQL (>= 9.4). 2. Create PostgreSQL database - $ createuser -SPRD sitnet - $ createdb sitnet --owner=sitnet + $ createuser -SPRD exam + $ createdb exam --owner=exam For tests - $ createdb sitnet_test --owner=sitnet - - For protractor - - $ createdb sitnet_protractor --owner=sitnet + $ createdb exam_test --owner=exam Requires that you have pg_hba.conf set up to accept local connections etc. - Note that you can configure database related parameters (and others) in the dev config file (conf/dev.conf) - -3. Get frontend dependencies - - $ cd ui - $ npm install - -4. Start sbt console - - $ cd .. - $ sbt -Dconfig.file=conf/dev.conf -jvm-debug 9999 + Note that you can configure database related parameters (and others) in the dev config file (/conf/dev.conf) - This opens up a debug port at 9999 and starts up webpack dev server at 8080. You can run webpack server independent of - sbt by passing the following build parameter +3. Get frontend dependencies and start frontend application in development mode - $ sbt -Dconfig.file=conf/dev.conf -DwithoutWebpackServer=true + $ npm install + $ npm start - in which case you can manage the server yourself in a separate terminal like this - - $ cd ui - $ npm start - -5. Inside sbt console start the app +4. In another tab or window start sbt console and run backend application in development mode + $ sbt -Dconfig.file=conf/dev.conf -jvm-debug 9999 -mem 2048 [exam] $ run -6. Open http://localhost:9000 in your browser - Accept the database migrations in case you see a prompt. - -## Skipping Karma and Protractor tests - -You can skip running UI tests by passing the following build parameter - - $ sbt -Dconfig.file=conf/dev.conf -DskipUiTests=true + This opens up a debug port at 9999 and allocates 2 Gb of heap memory for the JVM. -in which case the tests will not be executed after starting the app. - -## Running Protractor tests with SBT - -You can run protractor tests with sbt build using following command: - - $sbt run -Dconfig.resource=protractor.conf - -### Passing parameters to protractor - -You can pass parameters to protractor using _protractor.args_ property. -Passing multiple protractor parameters use comma (,) to separate parameters. - - -Dprotractor.args=--capabilities.browserName=firefox,--troubleshoot - -For example running specific test spec only: - - $sbt run -Dconfig.resource=protractor.conf -Dprotractor.args=--specs=protractor/e2e/teacher-exam-spec.js - -## Running Protractor tests in CI - -Using CI specific protractor configuration. - - $sbt run -Dconfig.resource=protractor.conf -Dprotractor.config=ciConf.js +5. Open http://localhost:4200 in your browser. + Accept the database migrations in case you see a prompt. ## More information For more information see [official installation instructions](https://wiki.eduuni.fi/display/CSCEXAM/Asennusohjeet) (in Finnish only) diff --git a/ui/angular.json b/angular.json similarity index 62% rename from ui/angular.json rename to angular.json index b0e86e788e..07abc48e90 100644 --- a/ui/angular.json +++ b/angular.json @@ -14,25 +14,20 @@ } }, "root": "", - "sourceRoot": "src", + "sourceRoot": "ui/src", "prefix": "xm", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/exam", - "index": "src/index.html", - "main": "src/main.ts", - "polyfills": "src/polyfills.ts", - "tsConfig": "tsconfig.app.json", + "index": "ui/src/index.html", + "main": "ui/src/main.ts", + "polyfills": "ui/src/polyfills.ts", + "tsConfig": "ui/tsconfig.app.json", "inlineStyleLanguage": "scss", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], + "assets": ["ui/src/favicon.ico", "ui/src/assets"], + "styles": ["ui/src/styles.scss"], "scripts": [] }, "configurations": { @@ -40,23 +35,23 @@ "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "2.1mb" + "maximumWarning": "2.2mb", + "maximumError": "2.3mb" }, { "type": "anyComponentStyle", "maximumWarning": "2kb", - "maximumError": "4kb" + "maximumError": "5kb" } ], "fileReplacements": [ { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" + "replace": "ui/src/environments/environment.ts", + "with": "ui/src/environments/environment.prod.ts" }, { - "replace": "src/app/interceptors/auth-interceptor.ts", - "with": "src/app/interceptors/auth-interceptor.prod.ts" + "replace": "ui/src/app/interceptors/auth-interceptor.ts", + "with": "ui/src/app/interceptors/auth-interceptor.prod.ts" } ], "outputHashing": "all", @@ -76,15 +71,15 @@ "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { - "browserTarget": "exam:build", - "proxyConfig": "src/proxy.conf.js" + "proxyConfig": "ui/src/proxy.conf.js", + "buildTarget": "exam:build" }, "configurations": { "production": { - "browserTarget": "exam:build:production" + "buildTarget": "exam:build:production" }, "development": { - "browserTarget": "exam:build:development" + "buildTarget": "exam:build:development" } }, "defaultConfiguration": "development" @@ -92,43 +87,33 @@ "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { - "browserTarget": "exam:build" + "buildTarget": "exam:build" } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { - "main": "src/test.ts", - "polyfills": "src/polyfills.ts", - "tsConfig": "tsconfig.spec.json", - "karmaConfig": "karma.conf.js", + "main": "ui/src/test.ts", + "polyfills": "ui/src/polyfills.ts", + "tsConfig": "ui/tsconfig.spec.json", + "karmaConfig": "ui/karma.conf.js", "inlineStyleLanguage": "scss", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], + "assets": ["ui/src/favicon.ico", "ui/src/assets"], + "styles": ["ui/src/styles.scss"], "scripts": [] } }, "lint": { "builder": "@angular-eslint/builder:lint", "options": { - "lintFilePatterns": [ - "src/**/*.ts", - "src/**/*.html" - ] + "lintFilePatterns": ["ui/src/**/*.ts", "ui/src/**/*.html"] } } } } }, "cli": { - "schematicCollections": [ - "@angular-eslint/schematics" - ], + "schematicCollections": ["@angular-eslint/schematics"], "analytics": false }, "schematics": { diff --git a/app/controllers/AccessibilityController.java b/app/controllers/AccessibilityController.java index 2ec6a7397a..8d6502f20b 100644 --- a/app/controllers/AccessibilityController.java +++ b/app/controllers/AccessibilityController.java @@ -18,7 +18,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.List; import models.Accessibility; import models.ExamRoom; @@ -30,25 +30,27 @@ public class AccessibilityController extends BaseController { @Restrict({ @Group("ADMIN") }) public Result addAccessibility(Http.Request request) { - Accessibility accessibility = bindForm(Accessibility.class, request); + Accessibility accessibility = new Accessibility(); + accessibility.setName(request.body().asJson().get("name").asText()); accessibility.save(); return ok(Json.toJson(accessibility)); } @Restrict({ @Group("ADMIN") }) public Result updateAccessibility(Http.Request request) { - Accessibility accessibility = bindForm(Accessibility.class, request); + Accessibility accessibility = new Accessibility(); + accessibility.setName(request.body().asJson().get("name").asText()); accessibility.update(); return ok(Json.toJson(accessibility)); } @Restrict({ @Group("ADMIN") }) public Result removeAccessibility(Long id) { - Accessibility accessibility = Ebean.find(Accessibility.class, id); + Accessibility accessibility = DB.find(Accessibility.class, id); if (accessibility == null) { return notFound(); } - Ebean + DB .find(ExamRoom.class) .where() .in("accessibilities", accessibility) @@ -63,7 +65,7 @@ public Result removeAccessibility(Long id) { @Restrict({ @Group("TEACHER"), @Group("ADMIN"), @Group("STUDENT") }) public Result getAccessibilities() { - List accessibilities = Ebean.find(Accessibility.class).findList(); + List accessibilities = DB.find(Accessibility.class).findList(); return ok(Json.toJson(accessibilities)); } } diff --git a/app/controllers/AttachmentController.java b/app/controllers/AttachmentController.java index 64a8f7b70a..6535be4402 100644 --- a/app/controllers/AttachmentController.java +++ b/app/controllers/AttachmentController.java @@ -15,15 +15,11 @@ package controllers; -import akka.stream.IOResult; -import akka.stream.javadsl.FileIO; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Pattern; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import java.io.File; import java.io.IOException; @@ -39,7 +35,10 @@ import models.questions.EssayAnswer; import models.questions.Question; import models.sections.ExamSectionQuestion; -import play.Logger; +import org.apache.pekko.stream.IOResult; +import org.apache.pekko.stream.javadsl.FileIO; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; import play.libs.Files; import play.mvc.Http; import play.mvc.Http.MultipartFormData.FilePart; @@ -51,8 +50,6 @@ public class AttachmentController extends BaseController implements LocalAttachmentInterface { - private static final Logger.ALogger logger = Logger.of(AttachmentController.class); - @Inject private ConfigReader configReader; @@ -67,8 +64,8 @@ public CompletionStage addAttachmentToQuestionAnswer(Http.Request reques FilePart filePart = mf.getFilePart(); long qid = Long.parseLong(mf.getForm().get("questionId")[0]); - // first check if answer already exist - ExamSectionQuestion question = Ebean + // first check if answer already exists + ExamSectionQuestion question = DB .find(ExamSectionQuestion.class) .fetch("essayAnswer") .where() @@ -95,7 +92,7 @@ public CompletionStage addAttachmentToQuestionAnswer(Http.Request reques question.getEssayAnswer().getId().toString() ); } catch (IOException e) { - return wrapAsPromise(internalServerError("sitnet_error_creating_attachment")); + return wrapAsPromise(internalServerError("i18n_error_creating_attachment")); } // Remove existing one if found EssayAnswer answer = question.getEssayAnswer(); @@ -128,7 +125,7 @@ private CompletionStage replaceAndFinish( public CompletionStage addAttachmentToQuestion(Http.Request request) { MultipartForm mf = getForm(request); long qid = Long.parseLong(mf.getForm().get("questionId")[0]); - Question question = Ebean + Question question = DB .find(Question.class) .fetch("examSectionQuestions.examSection.exam.parent") .where() @@ -142,7 +139,7 @@ public CompletionStage addAttachmentToQuestion(Http.Request request) { try { newFilePath = copyFile(filePart.getRef(), "question", Long.toString(qid)); } catch (IOException e) { - return wrapAsPromise(internalServerError("sitnet_error_creating_attachment")); + return wrapAsPromise(internalServerError("i18n_error_creating_attachment")); } return replaceAndFinish(question, filePart, newFilePath); } @@ -150,7 +147,7 @@ public CompletionStage addAttachmentToQuestion(Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Override public Result deleteQuestionAttachment(Long id) { - Question question = Ebean.find(Question.class, id); + Question question = DB.find(Question.class, id); if (question == null) { return notFound(); } @@ -166,9 +163,9 @@ public CompletionStage deleteQuestionAnswerAttachment(Long qid, Http.Req ExamSectionQuestion question; if (user.hasRole(Role.Name.STUDENT)) { question = - Ebean.find(ExamSectionQuestion.class).where().idEq(qid).eq("examSection.exam.creator", user).findOne(); + DB.find(ExamSectionQuestion.class).where().idEq(qid).eq("examSection.exam.creator", user).findOne(); } else { - question = Ebean.find(ExamSectionQuestion.class, qid); + question = DB.find(ExamSectionQuestion.class, qid); } if ( question != null && question.getEssayAnswer() != null && question.getEssayAnswer().getAttachment() != null @@ -188,13 +185,13 @@ public CompletionStage deleteQuestionAnswerAttachment(Long qid, Http.Req @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Override public CompletionStage deleteExamAttachment(Long id, Http.Request request) { - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (exam == null) { return wrapAsPromise(notFound()); } if (!user.hasRole(Role.Name.ADMIN) && !exam.isOwnedOrCreatedBy(user)) { - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } fileHandler.removePrevious(exam); @@ -204,9 +201,9 @@ public CompletionStage deleteExamAttachment(Long id, Http.Request reques @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Override public CompletionStage deleteFeedbackAttachment(Long id, Http.Request request) { - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); if (exam == null) { - return wrapAsPromise(notFound("sitnet_exam_not_found")); + return wrapAsPromise(notFound("i18n_exam_not_found")); } Comment comment = exam.getExamFeedback(); fileHandler.removePrevious(comment); @@ -217,9 +214,9 @@ public CompletionStage deleteFeedbackAttachment(Long id, Http.Request re @Pattern(value = "CAN_INSPECT_LANGUAGE") @Override public CompletionStage deleteStatementAttachment(Long id, Http.Request request) { - LanguageInspection inspection = Ebean.find(LanguageInspection.class).where().eq("exam.id", id).findOne(); + LanguageInspection inspection = DB.find(LanguageInspection.class).where().eq("exam.id", id).findOne(); if (inspection == null || inspection.getStatement() == null) { - return wrapAsPromise(notFound("sitnet_exam_not_found")); + return wrapAsPromise(notFound("i18n_exam_not_found")); } Comment comment = inspection.getStatement(); fileHandler.removePrevious(comment); @@ -232,20 +229,20 @@ public CompletionStage deleteStatementAttachment(Long id, Http.Request r public CompletionStage addAttachmentToExam(Http.Request request) { MultipartForm mf = getForm(request); long eid = Long.parseLong(mf.getForm().get("examId")[0]); - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { return wrapAsPromise(notFound()); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!user.hasRole(Role.Name.ADMIN) && !exam.isOwnedOrCreatedBy(user)) { - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } String newFilePath; FilePart filePart = mf.getFilePart(); try { newFilePath = copyFile(filePart.getRef(), "exam", Long.toString(eid)); } catch (IOException e) { - return wrapAsPromise(internalServerError("sitnet_error_creating_attachment")); + return wrapAsPromise(internalServerError("i18n_error_creating_attachment")); } return replaceAndFinish(exam, filePart, newFilePath); } @@ -254,7 +251,7 @@ public CompletionStage addAttachmentToExam(Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Override public CompletionStage addFeedbackAttachment(Long id, Http.Request request) { - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); if (exam == null) { return wrapAsPromise(notFound()); } @@ -270,7 +267,7 @@ public CompletionStage addFeedbackAttachment(Long id, Http.Request reque try { newFilePath = copyFile(filePart.getRef(), "exam", id.toString(), "feedback"); } catch (IOException e) { - return wrapAsPromise(internalServerError("sitnet_error_creating_attachment")); + return wrapAsPromise(internalServerError("i18n_error_creating_attachment")); } Comment comment = exam.getExamFeedback(); return replaceAndFinish(comment, filePart, newFilePath); @@ -280,7 +277,7 @@ public CompletionStage addFeedbackAttachment(Long id, Http.Request reque @Pattern(value = "CAN_INSPECT_LANGUAGE") @Override public CompletionStage addStatementAttachment(Long id, Http.Request request) { - LanguageInspection inspection = Ebean.find(LanguageInspection.class).where().eq("exam.id", id).findOne(); + LanguageInspection inspection = DB.find(LanguageInspection.class).where().eq("exam.id", id).findOne(); if (inspection == null) { return wrapAsPromise(notFound()); } @@ -296,7 +293,7 @@ public CompletionStage addStatementAttachment(Long id, Http.Request requ try { newFilePath = copyFile(filePart.getRef(), "exam", id.toString(), "inspectionstatement"); } catch (IOException e) { - return wrapAsPromise(internalServerError("sitnet_error_creating_attachment")); + return wrapAsPromise(internalServerError("i18n_error_creating_attachment")); } Comment comment = inspection.getStatement(); return replaceAndFinish(comment, filePart, newFilePath); @@ -310,14 +307,14 @@ public CompletionStage downloadQuestionAttachment(Long id, Http.Request Question question; if (user.hasRole(Role.Name.STUDENT)) { question = - Ebean + DB .find(Question.class) .where() .idEq(id) .eq("examSectionQuestions.examSection.exam.creator", user) .findOne(); } else { - question = Ebean.find(Question.class, id); + question = DB.find(Question.class, id); } if (question == null || question.getAttachment() == null) { return wrapAsPromise(notFound()); @@ -343,7 +340,7 @@ public CompletionStage downloadQuestionAnswerAttachment(Long qid, Http.R @Override public CompletionStage downloadExamAttachment(Long id, Http.Request request) { // TODO: Authorization? - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); if (exam == null || exam.getAttachment() == null) { return wrapAsPromise(notFound()); } @@ -357,9 +354,9 @@ public CompletionStage downloadFeedbackAttachment(Long id, Http.Request User user = request.attrs().get(Attrs.AUTHENTICATED_USER); Exam exam; if (user.hasRole(Role.Name.STUDENT)) { - exam = Ebean.find(Exam.class).where().idEq(id).eq("creator", user).findOne(); + exam = DB.find(Exam.class).where().idEq(id).eq("creator", user).findOne(); } else { - exam = Ebean.find(Exam.class, id); + exam = DB.find(Exam.class, id); } if (exam == null || exam.getExamFeedback() == null || exam.getExamFeedback().getAttachment() == null) { return wrapAsPromise(notFound()); @@ -372,7 +369,7 @@ public CompletionStage downloadFeedbackAttachment(Long id, Http.Request @Override public CompletionStage downloadStatementAttachment(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean + ExpressionList query = DB .find(Exam.class) .where() .idEq(id) @@ -395,7 +392,7 @@ public ConfigReader getConfigReader() { private CompletionStage serveAttachment(Attachment attachment) { File file = new File(attachment.getFilePath()); if (!file.exists()) { - return wrapAsPromise(internalServerError("sitnet_file_not_found_but_referred_in_database")); + return wrapAsPromise(internalServerError("i18n_file_not_found_but_referred_in_database")); } final Source> source = FileIO.fromPath(file.toPath()); return serveAsBase64Stream(attachment, source); @@ -404,14 +401,9 @@ private CompletionStage serveAttachment(Attachment attachment) { private ExamSectionQuestion getExamSectionQuestion(Http.Request request, Long id) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (user.hasRole(Role.Name.STUDENT)) { - return Ebean - .find(ExamSectionQuestion.class) - .where() - .idEq(id) - .eq("examSection.exam.creator", user) - .findOne(); + return DB.find(ExamSectionQuestion.class).where().idEq(id).eq("examSection.exam.creator", user).findOne(); } - return Ebean.find(ExamSectionQuestion.class, id); + return DB.find(ExamSectionQuestion.class, id); } private String copyFile(Files.TemporaryFile srcFile, String... pathParams) throws IOException { diff --git a/app/controllers/AvailabilityController.java b/app/controllers/AvailabilityController.java index 30efeb1380..735b57aa7f 100644 --- a/app/controllers/AvailabilityController.java +++ b/app/controllers/AvailabilityController.java @@ -18,7 +18,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -57,7 +57,7 @@ private static DateTime getSearchEndDate(DateTime start) { } private List getReservationsDuring(List reservations, Interval interval) { - return reservations.stream().filter(r -> interval.overlaps(r.toInterval())).collect(Collectors.toList()); + return reservations.stream().filter(r -> interval.overlaps(r.toInterval())).toList(); } private List toOneHourChunks(Interval i) { @@ -80,13 +80,13 @@ private Interval round(Interval slot) { @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result getAvailability(Long roomId, String day) { - ExamRoom room = Ebean.find(ExamRoom.class, roomId); + ExamRoom room = DB.find(ExamRoom.class, roomId); if (room == null) { return notFound(); } DateTime searchStart = parseSearchStartDate(day); DateTime searchEnd = getSearchEndDate(searchStart); - List reservations = Ebean + List reservations = DB .find(Reservation.class) .where() .eq("machine.room.id", roomId) @@ -107,7 +107,7 @@ public Result getAvailability(Long roomId, String day) { ) .map(this::round) .flatMap(i -> toOneHourChunks(i).stream()) - .collect(Collectors.toList()); + .toList(); allSlots.addAll(slotsForDate); window = window.plusDays(1); } @@ -122,7 +122,7 @@ public Result getAvailability(Long roomId, String day) { .entrySet() .stream() .map(e -> new Availability(e.getKey(), machineCount, e.getValue().size())) - .collect(Collectors.toList()); + .toList(); return ok(Json.toJson(availability)); } @@ -161,8 +161,7 @@ public int getReserved() { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Availability)) return false; - Availability a = (Availability) o; + if (!(o instanceof Availability a)) return false; return new EqualsBuilder().append(start, a.start).append(end, a.end).build(); } diff --git a/app/controllers/BaseAttachmentInterface.java b/app/controllers/BaseAttachmentInterface.java index 6c206cbf98..ad40e98fdd 100644 --- a/app/controllers/BaseAttachmentInterface.java +++ b/app/controllers/BaseAttachmentInterface.java @@ -18,8 +18,6 @@ import static play.mvc.Results.ok; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -32,7 +30,11 @@ import models.Exam; import models.User; import models.sections.ExamSectionQuestion; -import play.Logger; +import org.apache.commons.io.FileUtils; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.Files.TemporaryFile; import play.mvc.Http; import play.mvc.Result; @@ -69,8 +71,8 @@ default User getUser(Http.Request request) { return request.attrs().get(Attrs.AUTHENTICATED_USER); } - default Logger.ALogger logger() { - return Logger.of(getClass()); + default Logger logger() { + return LoggerFactory.getLogger(getClass()); } default CompletionStage serveAsBase64Stream(Attachment attachment, Source source) { @@ -88,7 +90,7 @@ default CompletionStage serveAsBase64Stream(String mimeType, String file ok() .chunked( source - .via(new ChunkMaker(3 * 1024)) + .via(new ChunkMaker(3 * (int) FileUtils.ONE_KB)) .map(byteString -> { final byte[] encoded = Base64.getEncoder().encode(byteString.toArray()); return ByteString.fromArray(encoded); @@ -116,7 +118,7 @@ default MultipartForm getForm(Http.Request request) throws IllegalArgumentExcept } Optional contentLength = request.header("Content-Length"); if (contentLength.isEmpty() || Long.parseLong(contentLength.get()) > getConfigReader().getMaxFileSize()) { - throw new IllegalArgumentException("sitnet_file_too_large"); + throw new IllegalArgumentException("i18n_file_too_large"); } return new MultipartForm(filePart, body.asFormUrlEncoded()); } diff --git a/app/controllers/CalendarController.java b/app/controllers/CalendarController.java index 01586fe6f5..f51b3c1952 100644 --- a/app/controllers/CalendarController.java +++ b/app/controllers/CalendarController.java @@ -15,7 +15,6 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; @@ -23,7 +22,8 @@ import exceptions.NotFoundException; import impl.CalendarHandler; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; +import io.ebean.Transaction; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -39,8 +39,10 @@ import models.Reservation; import models.User; import models.sections.ExamSection; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; @@ -71,13 +73,13 @@ public class CalendarController extends BaseController { @Inject protected ExternalReservationHandler externalReservationHandler; - private static final Logger.ALogger logger = Logger.of(CalendarController.class); + private final Logger logger = LoggerFactory.getLogger(CalendarController.class); @Authenticated @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result removeReservation(long id, Http.Request request) throws NotFoundException { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - final ExamEnrolment enrolment = Ebean + final ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("reservation.machine") @@ -93,12 +95,12 @@ public Result removeReservation(long id, Http.Request request) throws NotFoundEx final Reservation reservation = enrolment.getReservation(); DateTime now = dateTimeHandler.adjustDST(DateTime.now(), reservation); if (reservation.toInterval().isBefore(now) || reservation.toInterval().contains(now)) { - return forbidden("sitnet_reservation_in_effect"); + return forbidden("i18n_reservation_in_effect"); } enrolment.setReservation(null); enrolment.setReservationCanceled(true); - Ebean.save(enrolment); - Ebean.delete(Reservation.class, id); + DB.save(enrolment); + DB.delete(Reservation.class, id); // send email asynchronously final boolean isStudentUser = user.equals(enrolment.getUser()); @@ -132,13 +134,13 @@ protected Optional checkEnrolment(ExamEnrolment enrolment, User user, Co enrolment.getExam().getState() == Exam.State.STUDENT_STARTED || (oldReservation != null && oldReservation.toInterval().isBefore(DateTime.now())) ) { - return Optional.of(forbidden("sitnet_reservation_in_effect")); + return Optional.of(forbidden("i18n_reservation_in_effect")); } // No previous reservation or it's in the future // If no previous reservation, check if allowed to participate. This check is skipped if user already // has a reservation to this exam so that change of reservation is always possible. if (oldReservation == null && !isAllowedToParticipate(enrolment.getExam(), user)) { - return Optional.of(forbidden("sitnet_no_trials_left")); + return Optional.of(forbidden("i18n_no_trials_left")); } // Check that at least one section will end up in the exam Set sections = enrolment.getExam().getExamSections(); @@ -155,7 +157,7 @@ protected Optional checkEnrolment(ExamEnrolment enrolment, User user, Co enrolment.getExam().getState().equals(Exam.State.PUBLISHED) ) { // External reservation, assessment not returned yet. We must wait for it to arrive first - return Optional.of(forbidden("sitnet_enrolment_assessment_not_received")); + return Optional.of(forbidden("i18n_enrolment_assessment_not_received")); } return Optional.empty(); @@ -166,7 +168,7 @@ protected Optional checkEnrolment(ExamEnrolment enrolment, User user, Co public Result getCurrentEnrolment(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - Optional enrolment = Ebean + Optional enrolment = DB .find(ExamEnrolment.class) .fetch("optionalSections") .where() @@ -186,18 +188,18 @@ public CompletionStage createReservation(Http.Request request) { Long examId = request.attrs().get(Attrs.EXAM_ID); DateTime start = request.attrs().get(Attrs.START_DATE); DateTime end = request.attrs().get(Attrs.END_DATE); - Collection aids = request.attrs().get(Attrs.ACCESSABILITES); + Collection aids = request.attrs().get(Attrs.ACCESSIBILITIES); Collection sectionIds = request.attrs().get(Attrs.SECTION_IDS); - ExamRoom room = Ebean.find(ExamRoom.class, roomId); + ExamRoom room = DB.find(ExamRoom.class, roomId); DateTime now = dateTimeHandler.adjustDST(DateTime.now(), room); final User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + // Start manual transaction. - Ebean.beginTransaction(); - try { + try (Transaction tx = DB.beginTransaction()) { // Take pessimistic lock for user to prevent multiple reservations creating. - Ebean.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); - Optional optionalEnrolment = Ebean + DB.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); + Optional optionalEnrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("exam.examSections") @@ -212,7 +214,7 @@ public CompletionStage createReservation(Http.Request request) { .endJunction() .findOneOrEmpty(); if (optionalEnrolment.isEmpty()) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_not_found")); + return wrapAsPromise(forbidden("i18n_error_enrolment_not_found")); } ExamEnrolment enrolment = optionalEnrolment.get(); Optional badEnrolment = checkEnrolment(enrolment, user, sectionIds); @@ -228,7 +230,7 @@ public CompletionStage createReservation(Http.Request request) { aids ); if (machine.isEmpty()) { - return wrapAsPromise(forbidden("sitnet_no_machines_available")); + return wrapAsPromise(forbidden("i18n_no_machines_available")); } // Check that the proposed reservation is (still) doable @@ -239,7 +241,7 @@ public CompletionStage createReservation(Http.Request request) { proposedReservation.setUser(user); proposedReservation.setEnrolment(enrolment); if (!calendarHandler.isDoable(proposedReservation, aids)) { - return wrapAsPromise(forbidden("sitnet_no_machines_available")); + return wrapAsPromise(forbidden("i18n_no_machines_available")); } // We are good to go :) @@ -253,8 +255,8 @@ public CompletionStage createReservation(Http.Request request) { return externalReservationHandler .removeReservation(oldReservation, user, "") .thenCompose(result -> { - // Refetch enrolment - ExamEnrolment updatedEnrolment = Ebean + // Re-fetch enrolment + ExamEnrolment updatedEnrolment = DB .find(ExamEnrolment.class) .fetch("exam.executionType") .where() @@ -272,11 +274,8 @@ public CompletionStage createReservation(Http.Request request) { } } final CompletionStage result = makeNewReservation(enrolment, reservation, user, sectionIds); - Ebean.commitTransaction(); + tx.commit(); return result; - } finally { - // End transaction to release lock. - Ebean.endTransaction(); } } @@ -286,19 +285,19 @@ private CompletionStage makeNewReservation( User user, Collection sectionIds ) { - Ebean.save(reservation); + DB.save(reservation); enrolment.setReservation(reservation); enrolment.setReservationCanceled(false); enrolment.getOptionalSections().clear(); enrolment.update(); if (!sectionIds.isEmpty()) { - Set sections = Ebean.find(ExamSection.class).where().idIn(sectionIds).findSet(); + Set sections = DB.find(ExamSection.class).where().idIn(sectionIds).findSet(); enrolment.setOptionalSections(sections); } if (enrolment.getExam().isPrivate()) { enrolment.setNoShow(false); } - Ebean.save(enrolment); + DB.save(enrolment); Exam exam = enrolment.getExam(); // Send some emails asynchronously system @@ -322,7 +321,7 @@ public Result getSlots(Long examId, Long roomId, String day, Optional accessibilityIds = aids.orElse(Collections.emptyList()); return calendarHandler.getSlots(user, ee.getExam(), roomId, day, accessibilityIds); @@ -330,7 +329,7 @@ public Result getSlots(Long examId, Long roomId, String day, Optional - externalApi.getCoursesByCode(user, c).toScala.map(_.asScala.toResult(OK)) + externalApi.getCoursesByCode(user, c).asScala.map(_.asScala.toResult(Results.Ok)) case (Some("name"), Some(x)) if x.length >= 2 => Future { - Ebean - .find(classOf[Course]) + DB.find(classOf[Course]) .where .disjunction() .isNull("endDate") @@ -53,73 +59,59 @@ class CourseController @Inject()(externalApi: ExternalCourseHandler, configReade .endJunction() .ilike("name", s"%$x%") .orderBy("code") - .findList - .asScala + .list .filter(c => c.getStartDate == null || configReader .getCourseValidityDate(new DateTime(c.getStartDate)) - .isBeforeNow) - }.map(_.toResult(OK)) + .isBeforeNow + ) + }.map(_.toResult(Results.Ok)) case (Some("name"), Some(_)) => throw new IllegalArgumentException("Too short criteria") case _ => Future { - Ebean.find(classOf[Course]).where.isNotNull("name").orderBy("code").findList - }.map(_.asScala.toResult(OK)) - } - } + DB.find(classOf[Course]).where.isNotNull("name").orderBy("code").list + }.map(_.toResult(Results.Ok)) - def getUserCourses(user: User, - examIds: Option[List[Long]], - sectionIds: Option[List[Long]], - tagIds: Option[List[Long]]): Result = { - var query = Ebean.find(classOf[Course]).where.isNotNull("name") - if (!user.hasRole(Role.Name.ADMIN)) { + private def getUserCourses( + user: User, + examIds: Option[List[Long]], + sectionIds: Option[List[Long]], + tagIds: Option[List[Long]], + ownerIds: Option[List[Long]] + ): Result = + var query = DB.find(classOf[Course]).where.isNotNull("name") + if !user.hasRole(Role.Name.ADMIN) then query = query .eq("exams.examOwners", user) - } - if (examIds.getOrElse(Nil).nonEmpty) { - query = query.in("exams.id", examIds.get.asJava) - } - if (sectionIds.getOrElse(Nil).nonEmpty) { - query = query.in("exams.examSections.id", sectionIds.get.asJava) - } - if (tagIds.getOrElse(Nil).nonEmpty) { - query = - query.in("exams.examSections.sectionQuestions.question.parent.tags.id", tagIds.get.asJava) - } - query.orderBy("name desc").findList.asScala.toResult(OK) - } + if examIds.getOrElse(Nil).nonEmpty then query = query.in("exams.id", examIds.get.asJava) + if sectionIds.getOrElse(Nil).nonEmpty then query = query.in("exams.examSections.id", sectionIds.get.asJava) + if tagIds.getOrElse(Nil).nonEmpty then + query = query.in("exams.examSections.sectionQuestions.question.parent.tags.id", tagIds.get.asJava) - // Actions -> + if (ownerIds.getOrElse(Nil).nonEmpty) + query = query.in("exams.examOwners.id", ownerIds.get.asJava) + query.orderBy("name desc").findList.asScala.toResult(Results.Ok) + // Actions -> def getCourses(filterType: Option[String], criteria: Option[String]): Action[AnyContent] = - Action.async { request => - getAuthorizedUser(request, Seq("ADMIN", "TEACHER")) match { - case Some(user) => - listCourses(filterType, criteria, user) - case _ => - Future.successful(forbid()) - } + authenticated.andThen(authorized(Seq(Role.Name.ADMIN, Role.Name.TEACHER))).andThen(audited).async { request => + val user = request.attrs(Auth.ATTR_USER) + listCourses(filterType, criteria, user) } - def getCourse(id: Long): Action[AnyContent] = Action { request => - getAuthorizedUser(request, Seq("ADMIN", "TEACHER")) match { - case Some(_) => - Ebean.find(classOf[Course], id).toResult(OK) - case _ => forbid() + def getCourse(id: Long): Action[AnyContent] = + Action.andThen(authorized(Seq(Role.Name.TEACHER, Role.Name.ADMIN))).andThen(audited) { _ => + DB.find(classOf[Course], id).toResult(Results.Ok) } - } - def listUsersCourses(examIds: Option[List[Long]], - sectionIds: Option[List[Long]], - tagIds: Option[List[Long]]): Action[AnyContent] = Action { request => - getAuthorizedUser(request, Seq("ADMIN", "TEACHER")) match { - case Some(user) => - getUserCourses(user, examIds, sectionIds, tagIds) - case _ => - forbid() + def listUsersCourses( + examIds: Option[List[Long]], + sectionIds: Option[List[Long]], + tagIds: Option[List[Long]], + ownerIds: Option[List[Long]] + ): Action[AnyContent] = + authenticated.andThen(authorized(Seq(Role.Name.TEACHER, Role.Name.ADMIN))).andThen(audited) { request => + val user = request.attrs(Auth.ATTR_USER) + getUserCourses(user, examIds, sectionIds, tagIds, ownerIds) } - } - -} diff --git a/app/controllers/EnrolmentController.java b/app/controllers/EnrolmentController.java index a995f00b2d..09603f3d13 100644 --- a/app/controllers/EnrolmentController.java +++ b/app/controllers/EnrolmentController.java @@ -15,14 +15,14 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; import controllers.iop.transfer.api.ExternalReservationHandler; import impl.EmailComposer; import impl.ExternalCourseHandler; -import io.ebean.Ebean; +import io.ebean.DB; +import io.ebean.Transaction; import java.io.IOException; import java.util.Collection; import java.util.Date; @@ -42,9 +42,11 @@ import models.Reservation; import models.Role; import models.User; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; -import play.libs.concurrent.HttpExecutionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.libs.concurrent.ClassLoaderExecutionContext; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; @@ -62,7 +64,7 @@ public class EnrolmentController extends BaseController { private final boolean permCheckActive; - private static final Logger.ALogger logger = Logger.of(EnrolmentController.class); + private final Logger logger = LoggerFactory.getLogger(EnrolmentController.class); protected final EmailComposer emailComposer; @@ -72,7 +74,7 @@ public class EnrolmentController extends BaseController { private final EnrolmentRepository enrolmentRepository; - private final HttpExecutionContext httpExecutionContext; + private final ClassLoaderExecutionContext httpExecutionContext; private final ActorSystem actor; @@ -84,7 +86,7 @@ public EnrolmentController( ExternalCourseHandler externalCourseHandler, ExternalReservationHandler externalReservationHandler, EnrolmentRepository enrolmentRepository, - HttpExecutionContext httpExecutionContext, + ClassLoaderExecutionContext httpExecutionContext, ActorSystem actor, ConfigReader configReader, DateTimeHandler dateTimeHandler @@ -101,7 +103,7 @@ public EnrolmentController( @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result listEnrolledExams(String code) { - List exams = Ebean + List exams = DB .find(Exam.class) .fetch("creator", "firstName, lastName") .fetch("examLanguages") @@ -112,7 +114,7 @@ public Result listEnrolledExams(String code) { .eq("course.code", code) .eq("executionType.type", ExamExecutionType.Type.PUBLIC.toString()) .eq("state", Exam.State.PUBLISHED) - .ge("examActiveEndDate", new Date()) + .ge("periodEnd", new Date()) .findList(); return ok(exams); @@ -120,7 +122,7 @@ public Result listEnrolledExams(String code) { @Restrict({ @Group("ADMIN") }) public Result enrolmentsByReservation(Long id) { - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .fetch("user", "firstName, lastName, email") .fetch("exam") @@ -135,7 +137,7 @@ public Result enrolmentsByReservation(Long id) { @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result getEnrolledExamInfo(String code, Long id) { - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("course") .fetch("course.organisation") @@ -157,7 +159,7 @@ public Result getEnrolledExamInfo(String code, Long id) { .findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } return ok(exam); } @@ -171,6 +173,7 @@ private static ExamEnrolment makeEnrolment(Exam exam, User user) { enrolment.setUser(user); } enrolment.setExam(exam); + enrolment.setRandomDelay(); enrolment.save(); return enrolment; } @@ -178,19 +181,19 @@ private static ExamEnrolment makeEnrolment(Exam exam, User user) { @Authenticated @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result checkIfEnrolled(Long id, Http.Request request) { - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); if (exam == null) { return badRequest(); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (isAllowedToParticipate(exam, user)) { DateTime now = dateTimeHandler.adjustDST(new DateTime()); - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .where() .eq("user", user) .eq("exam.id", id) - .gt("exam.examActiveEndDate", now.toDate()) + .gt("exam.periodEnd", now.toDate()) .disjunction() .eq("exam.state", Exam.State.PUBLISHED) .eq("exam.state", Exam.State.STUDENT_STARTED) @@ -201,7 +204,7 @@ public Result checkIfEnrolled(Long id, Http.Request request) { .collect(Collectors.toList()); return ok(enrolments); } - return unauthorized("sitnet_no_trials_left"); + return unauthorized("i18n_no_trials_left"); } private boolean isActive(ExamEnrolment enrolment) { @@ -224,9 +227,9 @@ public Result removeEnrolment(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); ExamEnrolment enrolment; if (user.hasRole(Role.Name.STUDENT)) { - enrolment = Ebean.find(ExamEnrolment.class).fetch("exam").where().idEq(id).eq("user", user).findOne(); + enrolment = DB.find(ExamEnrolment.class).fetch("exam").where().idEq(id).eq("user", user).findOne(); } else { - enrolment = Ebean.find(ExamEnrolment.class).fetch("exam").where().idEq(id).findOne(); + enrolment = DB.find(ExamEnrolment.class).fetch("exam").where().idEq(id).findOne(); } if (enrolment == null) { return notFound("enrolment not found"); @@ -236,7 +239,7 @@ public Result removeEnrolment(Long id, Http.Request request) { return forbidden(); } if (enrolment.getReservation() != null || enrolment.getExaminationEventConfiguration() != null) { - return forbidden("sitnet_cancel_reservation_first"); + return forbidden("i18n_cancel_reservation_first"); } enrolment.delete(); return ok(); @@ -249,7 +252,7 @@ public Result removeEnrolment(Long id, Http.Request request) { public Result updateEnrolment(Long id, Http.Request request) { String info = request.attrs().getOptional(Attrs.ENROLMENT_INFORMATION).orElse(null); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExamEnrolment enrolment = Ebean.find(ExamEnrolment.class).where().idEq(id).eq("user", user).findOne(); + ExamEnrolment enrolment = DB.find(ExamEnrolment.class).where().idEq(id).eq("user", user).findOne(); if (enrolment == null) { return notFound("enrolment not found"); } @@ -259,7 +262,7 @@ public Result updateEnrolment(Long id, Http.Request request) { } private Optional getExam(Long eid, ExamExecutionType.Type type) { - return Ebean + return DB .find(Exam.class) .where() .eq("id", eid) @@ -273,18 +276,17 @@ private Optional getExam(Long eid, ExamExecutionType.Type type) { private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Type type, User user) { // Begin manual transaction - Ebean.beginTransaction(); - try { + try (Transaction tx = DB.beginTransaction()) { // Take pessimistic lock for user to prevent multiple enrolments creating. - Ebean.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); + DB.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); Optional possibleExam = getExam(eid, type); if (possibleExam.isEmpty()) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } Exam exam = possibleExam.get(); // Find existing enrolments for exam and user - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("examinationEventConfiguration") @@ -301,7 +303,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty (ee.getUser() != null && ee.getUser().equals(user)) || (ee.getPreEnrolledUserEmail() != null && ee.getPreEnrolledUserEmail().equals(user.getEmail())) ) - .collect(Collectors.toList()); + .toList(); // already enrolled (regular examination) if ( @@ -311,7 +313,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty e.getExam().getImplementation() == Exam.Implementation.AQUARIUM && e.getReservation() == null ) ) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_exists")); + return wrapAsPromise(forbidden("i18n_error_enrolment_exists")); } // already enrolled (BYOD examination) if ( @@ -322,7 +324,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty e.getExaminationEventConfiguration() == null ) ) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_exists")); + return wrapAsPromise(forbidden("i18n_error_enrolment_exists")); } // reservation in effect if ( @@ -331,7 +333,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty .map(ExamEnrolment::getReservation) .anyMatch(r -> r != null && r.toInterval().contains(dateTimeHandler.adjustDST(DateTime.now(), r))) ) { - return wrapAsPromise(forbidden("sitnet_reservation_in_effect")); + return wrapAsPromise(forbidden("i18n_reservation_in_effect")); } // examination event in effect if ( @@ -346,7 +348,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty .contains(dateTimeHandler.adjustDST(DateTime.now())) ) ) { - return wrapAsPromise(forbidden("sitnet_reservation_in_effect")); + return wrapAsPromise(forbidden("i18n_reservation_in_effect")); } List enrolmentsWithFutureReservations = enrolments .stream() @@ -354,7 +356,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty ee.getReservation() != null && ee.getReservation().toInterval().isAfter(dateTimeHandler.adjustDST(DateTime.now())) ) - .collect(Collectors.toList()); + .toList(); if (enrolmentsWithFutureReservations.size() > 1) { logger.error( "Several enrolments with future reservations found for user {} and exam {}", @@ -365,7 +367,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty } // reservation in the future, replace it if (!enrolmentsWithFutureReservations.isEmpty()) { - ExamEnrolment enrolment = enrolmentsWithFutureReservations.get(0); + ExamEnrolment enrolment = enrolmentsWithFutureReservations.getFirst(); Reservation reservation = enrolment.getReservation(); return externalReservationHandler .removeReservation(reservation, user, "") @@ -381,7 +383,7 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty e.getExaminationEventConfiguration() != null && e.getExaminationEventConfiguration().getExaminationEvent().toInterval(e.getExam()).isAfterNow() ) - .collect(Collectors.toList()); + .toList(); if (enrolmentsWithFutureExaminationEvents.size() > 1) { logger.error( "Several enrolments with future examination events found for user {} and exam {}", @@ -392,13 +394,13 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty } // examination event in the future, replace it if (!enrolmentsWithFutureExaminationEvents.isEmpty()) { - ExamEnrolment enrolment = enrolmentsWithFutureExaminationEvents.get(0); + ExamEnrolment enrolment = enrolmentsWithFutureExaminationEvents.getFirst(); enrolment.delete(); ExamEnrolment newEnrolment = makeEnrolment(exam, user); return wrapAsPromise(ok(newEnrolment)); } if (enrolments.size() == 1) { - ExamEnrolment enrolment = enrolments.get(0); + ExamEnrolment enrolment = enrolments.getFirst(); Reservation reservation = enrolment.getReservation(); if ( reservation != null && @@ -408,15 +410,12 @@ private CompletionStage doCreateEnrolment(Long eid, ExamExecutionType.Ty enrolment.getExam().getState().equals(Exam.State.PUBLISHED) ) { // External reservation, assessment not returned yet. We must wait for it to arrive first - return wrapAsPromise(forbidden("sitnet_enrolment_assessment_not_received")); + return wrapAsPromise(forbidden("i18n_enrolment_assessment_not_received")); } } ExamEnrolment newEnrolment = makeEnrolment(exam, user); - Ebean.commitTransaction(); + tx.commit(); return wrapAsPromise(ok(newEnrolment)); - } finally { - // End transaction to release lock. - Ebean.endTransaction(); } } @@ -425,7 +424,7 @@ private CompletionStage checkPermission(Long id, Collection code return doCreateEnrolment(id, ExamExecutionType.Type.PUBLIC, user); } else { logger.warn("Attempt to enroll for a course without permission from {}", user.toString()); - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } } @@ -451,20 +450,20 @@ public CompletionStage createEnrolment(final Long id, Http.Request reque public CompletionStage createStudentEnrolment(Long eid, Http.Request request) { Optional uid = request.attrs().getOptional(Attrs.USER_ID); Optional email = request.attrs().getOptional(Attrs.EMAIL); - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } ExamExecutionType.Type executionType = ExamExecutionType.Type.valueOf(exam.getExecutionType().getType()); User user; if (uid.isPresent()) { - user = Ebean.find(User.class, uid.get()); + user = DB.find(User.class, uid.get()); if (user == null) { return wrapAsPromise(badRequest("user not found")); } } else if (email.isPresent()) { - List users = Ebean + List users = DB .find(User.class) .where() .or() @@ -475,7 +474,7 @@ public CompletionStage createStudentEnrolment(Long eid, Http.Request req if (users.isEmpty()) { // Pre-enrolment // Check that we will not create duplicate enrolments for same email address - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .where() .eq("exam.id", eid) @@ -489,7 +488,7 @@ public CompletionStage createStudentEnrolment(Long eid, Http.Request req } } else if (users.size() == 1) { // User with email already exists - user = users.get(0); + user = users.getFirst(); } else { // Multiple users with same email -> not good return wrapAsPromise(internalServerError("multiple users found for email")); @@ -525,7 +524,7 @@ public CompletionStage createStudentEnrolment(Long eid, Http.Request req @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result removeStudentEnrolment(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .idEq(id) @@ -541,7 +540,7 @@ public Result removeStudentEnrolment(Long id, Http.Request request) { .endJunction() .findOne(); if (enrolment == null) { - return forbidden("sitnet_not_possible_to_remove_participant"); + return forbidden("i18n_not_possible_to_remove_participant"); } enrolment.delete(); return ok(); @@ -563,7 +562,7 @@ public CompletionStage getRoomInfoFromEnrolment(String hash, Http.Reques @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result addExaminationEventConfig(Long enrolmentId, Long configId, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Optional oee = Ebean + Optional oee = DB .find(ExamEnrolment.class) .where() .idEq(enrolmentId) @@ -574,7 +573,7 @@ public Result addExaminationEventConfig(Long enrolmentId, Long configId, Http.Re return notFound("enrolment not found"); } ExamEnrolment enrolment = oee.get(); - Optional optionalConfig = Ebean + Optional optionalConfig = DB .find(ExaminationEventConfiguration.class) .fetch("examEnrolments") .where() @@ -588,7 +587,7 @@ public Result addExaminationEventConfig(Long enrolmentId, Long configId, Http.Re ExaminationEventConfiguration config = optionalConfig.get(); ExaminationEvent event = config.getExaminationEvent(); if (config.getExamEnrolments().size() + 1 > event.getCapacity()) { - return forbidden("sitnet_error_max_enrolments_reached"); + return forbidden("i18n_error_max_enrolments_reached"); } enrolment.setExaminationEventConfiguration(config); enrolment.update(); @@ -609,7 +608,7 @@ public Result addExaminationEventConfig(Long enrolmentId, Long configId, Http.Re @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result removeExaminationEventConfig(Long enrolmentId, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Optional oee = Ebean + Optional oee = DB .find(ExamEnrolment.class) .where() .idEq(enrolmentId) @@ -639,7 +638,7 @@ public Result removeExaminationEventConfig(Long enrolmentId, Http.Request reques @Restrict({ @Group("ADMIN") }) public Result removeExaminationEvent(Long configId) { - ExaminationEventConfiguration config = Ebean.find(ExaminationEventConfiguration.class, configId); + ExaminationEventConfiguration config = DB.find(ExaminationEventConfiguration.class, configId); if (config == null) { return badRequest(); } @@ -648,7 +647,7 @@ public Result removeExaminationEvent(Long configId) { } ExaminationEvent event = config.getExaminationEvent(); Exam exam = config.getExam(); - Set enrolments = Ebean + Set enrolments = DB .find(ExamEnrolment.class) .fetch("user") .where() @@ -683,9 +682,9 @@ public Result removeExaminationEvent(Long configId) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result permitRetrial(Long id) { - ExamEnrolment enrolment = Ebean.find(ExamEnrolment.class, id); + ExamEnrolment enrolment = DB.find(ExamEnrolment.class, id); if (enrolment == null) { - return notFound("sitnet_not_found"); + return notFound("i18n_not_found"); } enrolment.setRetrialPermitted(true); enrolment.update(); diff --git a/app/controllers/ExamAnswerController.java b/app/controllers/ExamAnswerController.java index 9e716967a7..4a8ce8f8e1 100644 --- a/app/controllers/ExamAnswerController.java +++ b/app/controllers/ExamAnswerController.java @@ -3,7 +3,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.FetchConfig; import java.util.Optional; import javax.inject.Inject; @@ -33,20 +33,16 @@ public ExamAnswerController(MessagesApi messagesApi) { private boolean canReleaseAnswers(Exam exam) { ExamFeedbackConfig config = exam.getParent().getExamFeedbackConfig(); - switch (config.getReleaseType()) { - case ONCE_LOCKED: - return true; - case GIVEN_DATE: - return DateTime.now().isAfter(config.getReleaseDate().withTimeAtStartOfDay().plusDays(1)); - default: - return false; - } + return switch (config.getReleaseType()) { + case ONCE_LOCKED -> true; + case GIVEN_DATE -> DateTime.now().isAfter(config.getReleaseDate().withTimeAtStartOfDay().plusDays(1)); + }; } @Authenticated @Restrict(@Group({ "STUDENT" })) public Result getAnswers(Long eid, Http.Request request) { - Optional oe = Ebean + Optional oe = DB .find(Exam.class) .fetch("course", "name, code, credits") .fetch("grade", "name") @@ -55,7 +51,7 @@ public Result getAnswers(Long eid, Http.Request request) { .fetch( "examSections.sectionQuestions", "sequenceNumber, maxScore, answerInstructions, evaluationCriteria, expectedWordCount, evaluationType", - new FetchConfig().query() + FetchConfig.ofQuery() ) .fetch("examSections.sectionQuestions.question", "id, type, question") .fetch("examSections.sectionQuestions.question.attachment", "fileName") diff --git a/app/controllers/ExamController.java b/app/controllers/ExamController.java index 5f0e35ede5..d125181e10 100644 --- a/app/controllers/ExamController.java +++ b/app/controllers/ExamController.java @@ -15,20 +15,20 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; import impl.EmailComposer; import impl.ExamUpdater; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.FetchConfig; import io.ebean.Query; import io.ebean.text.PathProperties; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.TreeSet; @@ -40,10 +40,12 @@ import models.ExamType; import models.GradeScale; import models.Language; +import models.Permission; import models.Role; import models.Software; import models.User; import models.sections.ExamSection; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import org.joda.time.LocalDate; import play.libs.Json; @@ -85,7 +87,7 @@ public ExamController( } private static ExpressionList createPrototypeQuery() { - return Ebean + return DB .find(Exam.class) .fetch("course") .fetch("creator") @@ -134,7 +136,7 @@ public Result getExams(Optional filter, Http.Request request) { @Restrict({ @Group("ADMIN") }) public Result listPrintouts() { - List printouts = Ebean + List printouts = DB .find(Exam.class) .where() .eq("executionType.type", ExamExecutionType.Type.PRINTOUT.toString()) @@ -153,14 +155,18 @@ public Result listExams( Optional> courseIds, Optional> sectionIds, Optional> tagIds, + Optional> ownerIds, Http.Request request ) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); List courses = courseIds.orElse(Collections.emptyList()); List sections = sectionIds.orElse(Collections.emptyList()); List tags = tagIds.orElse(Collections.emptyList()); - PathProperties pp = PathProperties.parse("(id, name, course(id, code), examSections(id, name))"); - Query query = Ebean.find(Exam.class); + List owners = ownerIds.orElse(Collections.emptyList()); + PathProperties pp = PathProperties.parse( + "(id, name, examActiveStartDate, examActiveEndDate, course(id, code), examSections(id, name))" + ); + Query query = DB.find(Exam.class); pp.apply(query); ExpressionList el = query.where().isNotNull("name").isNotNull("course").isNull("parent"); if (!user.hasRole(Role.Name.ADMIN)) { @@ -175,6 +181,9 @@ public Result listExams( if (!tags.isEmpty()) { el = el.in("examSections.sectionQuestions.question.parent.tags.id", tags); } + if (!owners.isEmpty()) { + el = el.in("questionOwners.id", user); + } return ok(el.findList(), pp); } @@ -190,7 +199,7 @@ public Result getTeachersExams(Http.Request request) { "examInspections(id, user(id, firstName, lastName)), " + "examEnrolments(id, user(id), reservation(id, endAt), examinationEventConfiguration(examinationEvent(start))))" ); - Query query = Ebean.createQuery(Exam.class); + Query query = DB.createQuery(Exam.class); props.apply(query); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); List exams = query @@ -209,9 +218,9 @@ public Result getTeachersExams(Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result deleteExam(Long id, Http.Request request) { - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (user.hasRole(Role.Name.ADMIN) || exam.isOwnedOrCreatedBy(user)) { @@ -221,9 +230,9 @@ public Result deleteExam(Long id, Http.Request request) { exam.update(); return ok(); } - return forbidden("sitnet_exam_removal_not_possible"); + return forbidden("i18n_exam_removal_not_possible"); } - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } private static Exam doGetExam(Long id) { @@ -244,18 +253,25 @@ private static Exam doGetExam(Long id) { public Result getExam(Long id, Http.Request request) { Exam exam = doGetExam(id); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } - // decipher the settings passwords if any + // decipher the passwords if any if (exam.getImplementation() == Exam.Implementation.CLIENT_AUTH) { exam .getExaminationEventConfigurations() .forEach(eec -> { - String plainTextPwd = byodConfigHandler.getPlaintextPassword( + String plainTextSettingsPwd = byodConfigHandler.getPlaintextPassword( eec.getEncryptedSettingsPassword(), eec.getSettingsPasswordSalt() ); - eec.setSettingsPassword(plainTextPwd); + eec.setSettingsPassword(plainTextSettingsPwd); + if (eec.getEncryptedQuitPassword() != null) { + String plainTextQuitPwd = byodConfigHandler.getPlaintextPassword( + eec.getEncryptedQuitPassword(), + eec.getQuitPasswordSalt() + ); + eec.setQuitPassword(plainTextQuitPwd); + } }); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); @@ -263,24 +279,24 @@ public Result getExam(Long id, Http.Request request) { exam.getExamSections().forEach(s -> s.setSectionQuestions(new TreeSet<>(s.getSectionQuestions()))); return writeAnonymousResult(request, ok(exam), exam.isAnonymous()); } - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result getExamTypes() { - List types = Ebean.find(ExamType.class).where().ne("deprecated", true).findList(); + List types = DB.find(ExamType.class).where().ne("deprecated", true).findList(); return ok(types); } @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result getExamGradeScales() { - List scales = Ebean.find(GradeScale.class).fetch("grades").findList(); + List scales = DB.find(GradeScale.class).fetch("grades").findList(); return ok(scales); } @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result getExamExecutionTypes() { - List types = Ebean.find(ExamExecutionType.class).where().ne("active", false).findList(); + List types = DB.find(ExamExecutionType.class).where().ne("active", false).findList(); return ok(types); } @@ -288,7 +304,7 @@ public Result getExamExecutionTypes() { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getExamPreview(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("course") .fetch("executionType") @@ -296,7 +312,7 @@ public Result getExamPreview(Long id, Http.Request request) { .fetch("examLanguages") .fetch("examSections") .fetch("examSections.examMaterials") - .fetch("examSections.sectionQuestions", new FetchConfig().query()) + .fetch("examSections.sectionQuestions", FetchConfig.ofQuery()) .fetch("examSections.sectionQuestions.question") .fetch("examSections.sectionQuestions.question.attachment") .fetch("examSections.sectionQuestions.options") @@ -309,13 +325,13 @@ public Result getExamPreview(Long id, Http.Request request) { .idEq(id) .findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } if (exam.isShared() || exam.isInspectedOrCreatedOrOwnedBy(user) || user.hasRole(Role.Name.ADMIN)) { examUpdater.preparePreview(exam); return ok(exam); } - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } private Result handleExamUpdate(Exam exam, User user, Http.Request request) { @@ -359,7 +375,7 @@ public Result updateExam(Long id, Http.Request request) { .orElseGet(() -> handleExamUpdate(exam, user, request)) ); } else { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } } @@ -367,7 +383,7 @@ private boolean didGradeChange(Exam exam, int grading) { boolean canOverrideGrading = configReader.isCourseGradeScaleOverridable(); boolean changed = false; if (canOverrideGrading || exam.getCourse().getGradeScale() == null) { - GradeScale scale = Ebean.find(GradeScale.class).fetch("grades").where().idEq(grading).findOne(); + GradeScale scale = DB.find(GradeScale.class).fetch("grades").where().idEq(grading).findOne(); if (scale != null) { changed = exam.getGradeScale() == null || !exam.getGradeScale().equals(scale); } @@ -378,21 +394,21 @@ private boolean didGradeChange(Exam exam, int grading) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateExamSoftware(Long eid, Long sid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!examUpdater.isPermittedToUpdate(exam, user)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } - Software software = Ebean.find(Software.class, sid); + Software software = DB.find(Software.class, sid); if (exam.getSoftwareInfo().contains(software)) { exam.getSoftwareInfo().remove(software); } else { exam.getSoftwareInfo().add(software); if (!softwareRequirementDoable(exam)) { - return badRequest("sitnet_no_required_softwares"); + return badRequest("i18n_no_required_softwares"); } } exam.update(); @@ -400,17 +416,17 @@ public Result updateExamSoftware(Long eid, Long sid, Http.Request request) { } private static boolean softwareRequirementDoable(Exam exam) { - List machines = Ebean.find(ExamMachine.class).where().eq("archived", false).findList(); + List machines = DB.find(ExamMachine.class).where().eq("archived", false).findList(); - return machines.stream().anyMatch(m -> m.getSoftwareInfo().containsAll(exam.getSoftwareInfo())); + return machines.stream().anyMatch(m -> new HashSet<>(m.getSoftwareInfo()).containsAll(exam.getSoftwareInfo())); } @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateExamLanguage(Long eid, String code, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); return examUpdater @@ -425,7 +441,14 @@ public Result updateExamLanguage(Long eid, String code, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result copyExam(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Exam prototype = Ebean + String examinationType = formFactory.form().bindFromRequest(request).get("examinationType"); + if ( + Exam.Implementation.valueOf(examinationType) != Exam.Implementation.AQUARIUM && + !user.hasPermission(Permission.Type.CAN_CREATE_BYOD_EXAM) + ) { + return forbidden("i18n_access_forbidden"); + } + Exam prototype = DB .find(Exam.class) // TODO: check if all this fetching is necessary .fetch("creator", "id") .fetch("examType", "id, type") @@ -444,13 +467,12 @@ public Result copyExam(Long id, Http.Request request) { .idEq(id) .findOne(); if (prototype == null) { - return notFound("sitnet_exam_not_found"); + return notFound("i18n_exam_not_found"); } String type = formFactory.form().bindFromRequest(request).get("type"); - String examinationType = formFactory.form().bindFromRequest(request).get("examinationType"); - ExamExecutionType executionType = Ebean.find(ExamExecutionType.class).where().eq("type", type).findOne(); - if (type == null) { - return notFound("sitnet_execution_type_not_found"); + ExamExecutionType executionType = DB.find(ExamExecutionType.class).where().eq("type", type).findOne(); + if (executionType == null) { + return notFound("i18n_execution_type_not_found"); } // No sense in copying the AE config if grade scale is fixed to course (that will initially be NULL for a copy) if (prototype.getAutoEvaluationConfig() != null && !configReader.isCourseGradeScaleOverridable()) { @@ -467,10 +489,12 @@ public Result copyExam(Long id, Http.Request request) { copy.setExamFeedbackConfig(null); copy.setSubjectToLanguageInspection(null); DateTime now = DateTime.now().withTimeAtStartOfDay(); - copy.setExamActiveStartDate(now); - copy.setExamActiveEndDate(now.plusDays(1)); - // Force anonymous review if globally enabled - if (configReader.isAnonymousReviewEnabled()) { + copy.setPeriodStart(now); + copy.setPeriodEnd(now.plusDays(1)); + // Force anonymous review if globally enabled for public examinations + if (!copy.isPrivate()) { + copy.setAnonymous(false); + } else if (configReader.isAnonymousReviewEnabled()) { copy.setAnonymous(true); } copy.save(); @@ -482,7 +506,7 @@ public Result copyExam(Long id, Http.Request request) { public Result createExamDraft(Http.Request request) { String executionType = request.body().asJson().get("executionType").asText(); String implementation = request.body().asJson().get("implementation").asText(); - ExamExecutionType examExecutionType = Ebean + ExamExecutionType examExecutionType = DB .find(ExamExecutionType.class) .where() .eq("type", executionType) @@ -491,6 +515,12 @@ public Result createExamDraft(Http.Request request) { return badRequest("Unsupported execution type"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + if ( + Exam.Implementation.valueOf(implementation) != Exam.Implementation.AQUARIUM && + !user.hasPermission(Permission.Type.CAN_CREATE_BYOD_EXAM) + ) { + return forbidden("No permission to create home examinations"); + } Exam exam = new Exam(); exam.generateHash(); exam.setState(Exam.State.DRAFT); @@ -511,17 +541,17 @@ public Result createExamDraft(Http.Request request) { examSection.save(); exam.getExamSections().add(examSection); - exam.getExamLanguages().add(Ebean.find(Language.class, "fi")); // TODO: configurable? - exam.setExamType(Ebean.find(ExamType.class, 2)); // Final + exam.getExamLanguages().add(DB.find(Language.class, "fi")); // TODO: configurable? + exam.setExamType(DB.find(ExamType.class, 2)); // Final DateTime start = DateTime.now().withTimeAtStartOfDay(); if (!exam.isPrintout()) { - exam.setExamActiveStartDate(start); - exam.setExamActiveEndDate(start.plusDays(1)); + exam.setPeriodStart(start); + exam.setPeriodEnd(start.plusDays(1)); } - exam.setDuration(configReader.getExamDurations().get(0)); + exam.setDuration(configReader.getExamDurations().getFirst()); if (configReader.isCourseGradeScaleOverridable()) { - exam.setGradeScale(Ebean.find(GradeScale.class).findList().get(0)); + exam.setGradeScale(DB.find(GradeScale.class).findList().getFirst()); } exam.save(); @@ -529,7 +559,6 @@ public Result createExamDraft(Http.Request request) { exam.getExamOwners().add(user); exam.setTrialCount(1); - exam.setExpanded(true); exam.save(); ObjectNode part = Json.newObject(); @@ -540,46 +569,46 @@ public Result createExamDraft(Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateCourse(Long eid, Long cid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!examUpdater.isAllowedToUpdate(exam, user)) { - return forbidden("sitnet_error_future_reservations_exist"); + return forbidden("i18n_error_future_reservations_exist"); } if (exam.isOwnedOrCreatedBy(user) || user.hasRole(Role.Name.ADMIN)) { - Course course = Ebean.find(Course.class, cid); + Course course = DB.find(Course.class, cid); if (course == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } if (course.getStartDate() != null) { DateTime validity = configReader.getCourseValidityDate(new DateTime(course.getStartDate())); if (validity.isAfterNow()) { - return forbidden("sitnet_error_course_not_active"); + return forbidden("i18n_error_course_not_active"); } } if (course.getEndDate() != null && course.getEndDate().before(new Date())) { - return forbidden("sitnet_error_course_not_active"); + return forbidden("i18n_error_course_not_active"); } exam.setCourse(course); exam.save(); return ok(); } else { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } } private static Query prototypeQuery() { - return Ebean + return DB .find(Exam.class) .fetch("course") .fetch("course.organisation") .fetch("course.gradeScale") - .fetch("course.gradeScale.grades", new FetchConfig().query()) + .fetch("course.gradeScale.grades", FetchConfig.ofQuery()) .fetch("examType") .fetch("autoEvaluationConfig") - .fetch("autoEvaluationConfig.gradeEvaluations", new FetchConfig().query()) + .fetch("autoEvaluationConfig.gradeEvaluations", FetchConfig.ofQuery()) .fetch("examFeedbackConfig") .fetch("executionType") .fetch("examinationDates") @@ -593,7 +622,7 @@ private static Query prototypeQuery() { ) .fetch("examSections.sectionQuestions.question", "id, type, question, shared") .fetch("examSections.sectionQuestions.question.attachment", "fileName") - .fetch("examSections.sectionQuestions.options", new FetchConfig().query()) + .fetch("examSections.sectionQuestions.options", FetchConfig.ofQuery()) .fetch( "examSections.sectionQuestions.options.option", "id, option, correctOption, defaultScore, claimChoiceType" diff --git a/app/controllers/ExamInspectionController.java b/app/controllers/ExamInspectionController.java index a59c72c52b..8931a9f045 100644 --- a/app/controllers/ExamInspectionController.java +++ b/app/controllers/ExamInspectionController.java @@ -15,12 +15,11 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Model; import java.util.Optional; import java.util.Set; @@ -31,6 +30,7 @@ import models.ExamInspection; import models.Role; import models.User; +import org.apache.pekko.actor.ActorSystem; import play.libs.Json; import play.mvc.Http; import play.mvc.Result; @@ -52,14 +52,14 @@ public class ExamInspectionController extends BaseController { @With(CommentSanitizer.class) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result addInspection(Long eid, Long uid, Http.Request request) { - User recipient = Ebean.find(User.class, uid); - Exam exam = Ebean.find(Exam.class, eid); + User recipient = DB.find(User.class, uid); + Exam exam = DB.find(Exam.class, eid); if (exam == null || recipient == null) { return notFound(); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!user.hasRole(Role.Name.ADMIN) && !exam.isOwnedOrCreatedBy(user)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } if (isInspectorOf(recipient, exam)) { return forbidden("already an inspector"); @@ -67,7 +67,7 @@ public Result addInspection(Long eid, Long uid, Http.Request request) { Optional comment = request.attrs().getOptional(Attrs.COMMENT); // Exam name required before adding inspectors that are to receive an email notification if ((exam.getName() == null || exam.getName().isEmpty()) && comment.isPresent()) { - return badRequest("sitnet_exam_name_missing_or_too_short"); + return badRequest("i18n_exam_name_missing_or_too_short"); } ExamInspection inspection = new ExamInspection(); inspection.setExam(exam); @@ -113,7 +113,7 @@ private static boolean isInspectorOf(User user, Exam exam) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getExamInspections(Long id) { - Set inspections = Ebean + Set inspections = DB .find(ExamInspection.class) .fetch("user", "id, email, firstName, lastName") .where() @@ -125,7 +125,7 @@ public Result getExamInspections(Long id) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result setInspectionOutcome(Long id, Http.Request request) { boolean ready = Boolean.parseBoolean(formFactory.form().bindFromRequest(request).get("ready")); - ExamInspection inspection = Ebean.find(ExamInspection.class, id); + ExamInspection inspection = DB.find(ExamInspection.class, id); if (inspection == null) { return notFound(); @@ -138,9 +138,9 @@ public Result setInspectionOutcome(Long id, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result deleteInspection(Long id) { - ExamInspection inspection = Ebean.find(ExamInspection.class, id); + ExamInspection inspection = DB.find(ExamInspection.class, id); if (inspection == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } User inspector = inspection.getUser(); Exam exam = inspection.getExam(); diff --git a/app/controllers/ExamMachineController.java b/app/controllers/ExamMachineController.java index 7c737f0321..52f7267e0f 100644 --- a/app/controllers/ExamMachineController.java +++ b/app/controllers/ExamMachineController.java @@ -19,12 +19,11 @@ import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Query; import io.ebean.text.PathProperties; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import models.ExamMachine; import models.ExamRoom; import models.Reservation; @@ -38,7 +37,7 @@ public class ExamMachineController extends BaseController { @Restrict({ @Group("ADMIN") }) public Result getExamMachines() { - List machines = Ebean.find(ExamMachine.class).where().eq("archived", false).findList(); + List machines = DB.find(ExamMachine.class).where().eq("archived", false).findList(); return ok(machines); } @@ -46,7 +45,7 @@ public Result getExamMachines() { @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public Result getExamMachine(Long id) { PathProperties pp = PathProperties.parse("(*, softwareInfo(*), room(name, buildingName))"); - Query query = Ebean.find(ExamMachine.class); + Query query = DB.find(ExamMachine.class); pp.apply(query); ExamMachine machine = query.where().idEq(id).findOne(); return ok(machine, pp); @@ -54,7 +53,7 @@ public Result getExamMachine(Long id) { @Restrict({ @Group("ADMIN") }) public Result getExamMachineReservationsFromNow(Long id) { - List reservations = Ebean + List reservations = DB .find(Reservation.class) .where() .eq("machine.id", id) @@ -83,20 +82,16 @@ public Result updateExamMachine(Long id, Http.Request request) { "outOfService" ) .get(); - ExamMachine dest = Ebean.find(ExamMachine.class, id); + ExamMachine dest = DB.find(ExamMachine.class, id); if (dest == null) { return notFound(); } - if (src.getIpAddress().length() > 0) { - List machines = Ebean.find(ExamMachine.class).findList(); - List ips = machines - .stream() - .filter(m -> !m.equals(dest)) - .map(ExamMachine::getIpAddress) - .collect(Collectors.toList()); + if (!src.getIpAddress().isEmpty()) { + List machines = DB.find(ExamMachine.class).findList(); + List ips = machines.stream().filter(m -> !m.equals(dest)).map(ExamMachine::getIpAddress).toList(); if (ips.contains(src.getIpAddress())) { - return forbidden("sitnet_error_ip_address_exists_for_room"); + return forbidden("i18n_error_ip_address_exists_for_room"); } } @@ -119,7 +114,7 @@ public Result updateExamMachine(Long id, Http.Request request) { @Restrict({ @Group("ADMIN") }) public Result resetMachineSoftware(Long mid) { - ExamMachine machine = Ebean.find(ExamMachine.class, mid); + ExamMachine machine = DB.find(ExamMachine.class, mid); if (machine == null) { return notFound(); } @@ -133,12 +128,12 @@ public Result resetMachineSoftware(Long mid) { @Restrict({ @Group("ADMIN") }) public Result updateMachineSoftware(Long mid, Long sid) { - ExamMachine machine = Ebean.find(ExamMachine.class, mid); + ExamMachine machine = DB.find(ExamMachine.class, mid); if (machine == null) { return notFound(); } boolean isTurnedOn = false; - Software software = Ebean.find(Software.class, sid); + Software software = DB.find(Software.class, sid); if (machine.getSoftwareInfo().contains(software)) { machine.getSoftwareInfo().remove(software); } else { @@ -153,17 +148,15 @@ public Result updateMachineSoftware(Long mid, Long sid) { } @Restrict({ @Group("ADMIN") }) - public Result insertExamMachine(Long id, Http.Request request) { - ExamRoom room = Ebean.find(ExamRoom.class, id); + public Result insertExamMachine(Long id) { + var room = DB.find(ExamRoom.class, id); if (room == null) { return notFound(); } - ExamMachine machine = bindForm(ExamMachine.class, request); + var machine = new ExamMachine(); room.getExamMachines().add(machine); room.save(); - machine.save(); - return ok(machine); } @@ -174,8 +167,8 @@ public Result removeExamMachine(Long id) { } @Restrict({ @Group("TEACHER"), @Group("ADMIN"), @Group("STUDENT") }) - public Result getSoftwares() { - List softwares = Ebean + public Result listSoftware() { + List software = DB .find(Software.class) .where() .or() @@ -184,26 +177,26 @@ public Result getSoftwares() { .endOr() .findList(); - return ok(softwares); + return ok(software); } @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getSoftware(Long id) { - Software software = Ebean.find(Software.class, id); + Software software = DB.find(Software.class, id); return ok(software); } private Optional checkSoftwareName(String name) { - List sw = Ebean.find(Software.class).where().ieq("name", name).findList(); + List sw = DB.find(Software.class).where().ieq("name", name).findList(); return sw.isEmpty() ? Optional.empty() : Optional.of(badRequest("Software with that name already exists")); } @Restrict(@Group({ "ADMIN" })) - public Result addSoftware(String name, Http.Request request) { - Software software = bindForm(Software.class, request); + public Result addSoftware(String name) { return checkSoftwareName(name) .orElseGet(() -> { + Software software = new Software(); software.setName(name); software.save(); return ok(software); @@ -212,7 +205,7 @@ public Result addSoftware(String name, Http.Request request) { @Restrict(@Group({ "ADMIN" })) public Result updateSoftware(Long id, String name) { - Software software = Ebean.find(Software.class, id); + Software software = DB.find(Software.class, id); if (software == null) { return notFound(); } @@ -226,7 +219,7 @@ public Result updateSoftware(Long id, String name) { @Restrict(@Group({ "ADMIN" })) public Result removeSoftware(Long id) { - Software software = Ebean.find(Software.class, id); + Software software = DB.find(Software.class, id); if (software == null) { return notFound(); } diff --git a/app/controllers/ExamMaterialController.java b/app/controllers/ExamMaterialController.java index a2afb0931d..97ed2c721c 100644 --- a/app/controllers/ExamMaterialController.java +++ b/app/controllers/ExamMaterialController.java @@ -19,7 +19,7 @@ import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import controllers.base.SectionQuestionHandler; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import java.util.Optional; import java.util.Set; @@ -56,7 +56,7 @@ public Result createMaterial(Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result listMaterials(Http.Request request) { - Set materials = Ebean + Set materials = DB .find(ExamMaterial.class) .where() .eq("creator", request.attrs().get(Attrs.AUTHENTICATED_USER)) @@ -67,18 +67,18 @@ public Result listMaterials(Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeMaterial(Long materialId, Http.Request request) { - ExamMaterial em = Ebean.find(ExamMaterial.class, materialId); + ExamMaterial em = DB.find(ExamMaterial.class, materialId); if (em == null || !em.getCreator().equals(request.attrs().get(Attrs.AUTHENTICATED_USER))) { return notFound(); } - Ebean.delete(ExamMaterial.class, materialId); + DB.delete(ExamMaterial.class, materialId); return ok(); } @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateMaterial(Long materialId, Http.Request request) { - ExamMaterial dst = Ebean.find(ExamMaterial.class, materialId); + ExamMaterial dst = DB.find(ExamMaterial.class, materialId); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (dst == null || !dst.getCreator().equals(user)) { return notFound(); @@ -90,7 +90,7 @@ public Result updateMaterial(Long materialId, Http.Request request) { } private Optional getSection(Long sectionId, User user) { - return Ebean.find(ExamSection.class).where().idEq(sectionId).eq("exam.examOwners", user).findOneOrEmpty(); + return DB.find(ExamSection.class).where().idEq(sectionId).eq("exam.examOwners", user).findOneOrEmpty(); } private Optional getOwnershipError(ExamMaterial em, User user) { @@ -100,7 +100,7 @@ private Optional getOwnershipError(ExamMaterial em, User user) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result addMaterialForSection(Long sectionId, Long materialId, Http.Request request) { - ExamMaterial em = Ebean.find(ExamMaterial.class, materialId); + ExamMaterial em = DB.find(ExamMaterial.class, materialId); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); return getOwnershipError(em, user) .orElseGet(() -> { @@ -118,7 +118,7 @@ public Result addMaterialForSection(Long sectionId, Long materialId, Http.Reques @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeMaterialFromSection(Long sectionId, Long materialId, Http.Request request) { - ExamMaterial em = Ebean.find(ExamMaterial.class, materialId); + ExamMaterial em = DB.find(ExamMaterial.class, materialId); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); return getOwnershipError(em, user) .orElseGet(() -> { diff --git a/app/controllers/ExamOwnerController.java b/app/controllers/ExamOwnerController.java index b312857901..eb6794e654 100644 --- a/app/controllers/ExamOwnerController.java +++ b/app/controllers/ExamOwnerController.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import models.Exam; import models.Role; import models.User; @@ -34,7 +34,7 @@ public class ExamOwnerController extends BaseController { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getExamOwners(Long id) { - Exam exam = Ebean.find(Exam.class).fetch("examOwners").where().idEq(id).findOne(); + Exam exam = DB.find(Exam.class).fetch("examOwners").where().idEq(id).findOne(); if (exam == null) { return notFound(); } @@ -57,14 +57,14 @@ public Result getExamOwners(Long id) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result insertExamOwner(Long eid, Long uid, Http.Request request) { - final User owner = Ebean.find(User.class, uid); - final Exam exam = Ebean.find(Exam.class, eid); + final User owner = DB.find(User.class, uid); + final Exam exam = DB.find(Exam.class, eid); if (exam == null || owner == null) { return notFound(); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!user.hasRole(Role.Name.ADMIN) && !exam.isOwnedOrCreatedBy(user)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } exam.getExamOwners().add(owner); exam.update(); @@ -74,14 +74,14 @@ public Result insertExamOwner(Long eid, Long uid, Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeExamOwner(Long eid, Long uid, Http.Request request) { - final User owner = Ebean.find(User.class, uid); - final Exam exam = Ebean.find(Exam.class, eid); + final User owner = DB.find(User.class, uid); + final Exam exam = DB.find(Exam.class, eid); if (exam == null) { return notFound(); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!user.hasRole(Role.Name.ADMIN) && !exam.isOwnedOrCreatedBy(user)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } if (owner != null) { exam.getExamOwners().remove(owner); diff --git a/app/controllers/ExamRecordController.java b/app/controllers/ExamRecordController.java index 7ff32c0325..efda675106 100644 --- a/app/controllers/ExamRecordController.java +++ b/app/controllers/ExamRecordController.java @@ -15,18 +15,16 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.Base64; import java.util.Collection; -import java.util.Date; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.inject.Inject; @@ -40,10 +38,12 @@ import models.Role; import models.User; import models.dto.ExamScore; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.data.DynamicForm; import play.db.ebean.Transactional; import play.mvc.Http; @@ -70,7 +70,7 @@ public class ExamRecordController extends BaseController { private final ActorSystem actor; private static final String XLSX_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - private static final Logger.ALogger logger = Logger.of(ExamRecordController.class); + private final Logger logger = LoggerFactory.getLogger(ExamRecordController.class); @Inject public ExamRecordController( @@ -94,7 +94,7 @@ public ExamRecordController( @Transactional public Result addExamRecord(Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); - final Optional optionalExam = Ebean + final Optional optionalExam = DB .find(Exam.class) .fetch("parent") .fetch("parent.creator") @@ -103,7 +103,7 @@ public Result addExamRecord(Http.Request request) { .idEq(Long.parseLong(df.get("id"))) .findOneOrEmpty(); if (optionalExam.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); Exam exam = optionalExam.get(); @@ -111,7 +111,7 @@ public Result addExamRecord(Http.Request request) { .orElseGet(() -> { exam.setState(Exam.State.GRADED_LOGGED); exam.update(); - ExamParticipation participation = Ebean + ExamParticipation participation = DB .find(ExamParticipation.class) .fetch("user") .where() @@ -144,7 +144,7 @@ public Result addExamRecord(Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result registerExamWithoutRecord(Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); - final Optional optionalExam = Ebean + final Optional optionalExam = DB .find(Exam.class) .fetch("languageInspection") .fetch("parent") @@ -153,7 +153,7 @@ public Result registerExamWithoutRecord(Http.Request request) { .idEq(Long.parseLong(df.get("id"))) .findOneOrEmpty(); if (optionalExam.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = optionalExam.get(); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); @@ -173,7 +173,7 @@ public Result exportExamRecordsAsCsv(Long startDate, Long endDate) { try { file = csvBuilder.build(startDate, endDate); } catch (IOException e) { - return internalServerError("sitnet_error_creating_csv_file"); + return internalServerError("i18n_error_creating_csv_file"); } String contentDisposition = fileHandler.getContentDisposition(file); String content = fileHandler.encodeAndDelete(file); @@ -188,7 +188,7 @@ public Result exportSelectedExamRecordsAsCsv(Long examId, Http.Request request) try { file = csvBuilder.build(examId, childIds); } catch (IOException e) { - return internalServerError("sitnet_error_creating_csv_file"); + return internalServerError("i18n_error_creating_csv_file"); } String contentDisposition = fileHandler.getContentDisposition(file); String content = fileHandler.encodeAndDelete(file); @@ -203,7 +203,7 @@ public Result exportSelectedExamRecordsAsExcel(Long examId, Http.Request request try { bos = excelBuilder.build(examId, childIds); } catch (IOException e) { - return internalServerError("sitnet_error_creating_csv_file"); + return internalServerError("i18n_error_creating_csv_file"); } return ok(Base64.getEncoder().encodeToString(bos.toByteArray())) .withHeader("Content-Disposition", "attachment; filename=\"exam_records.xlsx\"") @@ -251,23 +251,23 @@ private Optional validateExamState(Exam exam, boolean gradeRequired, Use exam.hasState(Exam.State.ABORTED, Exam.State.GRADED_LOGGED, Exam.State.ARCHIVED) || exam.getExamRecord() != null ) { - return Optional.of(forbidden("sitnet_error_exam_already_graded_logged")); + return Optional.of(forbidden("i18n_error_exam_already_graded_logged")); } return Optional.empty(); } - private static ExamRecord createRecord(Exam exam, ExamParticipation participation) { + private ExamRecord createRecord(Exam exam, ExamParticipation participation) { User student = participation.getUser(); User teacher = exam.getGradedByUser(); ExamRecord record = new ExamRecord(); record.setExam(exam); record.setStudent(student); record.setTeacher(teacher); - record.setTimeStamp(new Date()); + record.setTimeStamp(DateTime.now()); return record; } - private static ExamScore createScore(ExamRecord record, DateTime examDate) { + private ExamScore createScore(ExamRecord record, DateTime examDate) { Exam exam = record.getExam(); ExamScore score = new ExamScore(); score.setAdditionalInfo(exam.getAdditionalInfo()); @@ -299,7 +299,7 @@ private static ExamScore createScore(ExamRecord record, DateTime examDate) { score.setIdentifier(exam.getCourse().getIdentifier()); GradeScale scale = exam.getGradeScale() == null ? exam.getCourse().getGradeScale() : exam.getGradeScale(); if (scale.getExternalRef() != null) { - score.setGradeScale(scale.getExternalRef().toString()); + score.setGradeScale(scale.getExternalRef()); } else { score.setGradeScale(scale.getDescription()); } diff --git a/app/controllers/ExamSectionController.java b/app/controllers/ExamSectionController.java index 581350fed0..fbd2269f72 100644 --- a/app/controllers/ExamSectionController.java +++ b/app/controllers/ExamSectionController.java @@ -23,7 +23,7 @@ import controllers.base.BaseController; import controllers.base.SectionQuestionHandler; import impl.ExamUpdaterImpl; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.text.PathProperties; import java.util.ArrayList; @@ -64,7 +64,7 @@ public class ExamSectionController extends BaseController implements SectionQues @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result insertSection(Long id, Http.Request request) { - Optional oe = Ebean + Optional oe = DB .find(Exam.class) .fetch("examOwners") .fetch("examSections") @@ -72,14 +72,14 @@ public Result insertSection(Long id, Http.Request request) { .idEq(id) .findOneOrEmpty(); if (oe.isEmpty()) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); Exam exam = oe.get(); // Not allowed to add a section if optional sections exist and there are upcoming reservations boolean optionalSectionsExist = exam.getExamSections().stream().anyMatch(ExamSection::isOptional); if (optionalSectionsExist && !examUpdater.isAllowedToUpdate(exam, user)) { - return forbidden("sitnet_error_future_reservations_exist"); + return forbidden("i18n_error_future_reservations_exist"); } if (exam.isOwnedOrCreatedBy(user) || user.hasRole(Role.Name.ADMIN)) { ExamSection section = new ExamSection(); @@ -93,30 +93,30 @@ public Result insertSection(Long id, Http.Request request) { section.save(); return ok(section, PathProperties.parse("(*, examMaterials(*), sectionQuestions(*))")); } else { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } } @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeSection(Long eid, Long sid, Http.Request request) { - Optional oe = Ebean + Optional oe = DB .find(Exam.class) .fetch("examOwners") .fetch("examSections") .where() .idEq(eid) .findOneOrEmpty(); - ExamSection section = Ebean.find(ExamSection.class, sid); + ExamSection section = DB.find(ExamSection.class, sid); if (oe.isEmpty() || section == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } Exam exam = oe.get(); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); // Not allowed to remove a section if optional sections exist and there are upcoming reservations boolean optionalSectionsExist = exam.getExamSections().stream().anyMatch(ExamSection::isOptional); if (optionalSectionsExist && !examUpdater.isAllowedToUpdate(exam, user)) { - return forbidden("sitnet_error_future_reservations_exist"); + return forbidden("i18n_error_future_reservations_exist"); } if (exam.isOwnedOrCreatedBy(user) || user.hasRole(Role.Name.ADMIN)) { exam.getExamSections().remove(section); @@ -132,27 +132,27 @@ public Result removeSection(Long eid, Long sid, Http.Request request) { section.delete(); return ok(); } else { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } } @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateSection(Long eid, Long sid, Http.Request request) { - Optional oe = Ebean + Optional oe = DB .find(Exam.class) .fetch("examOwners") .fetch("examSections") .where() .idEq(eid) .findOneOrEmpty(); - ExamSection section = Ebean.find(ExamSection.class, sid); + ExamSection section = DB.find(ExamSection.class, sid); if (oe.isEmpty() || section == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!oe.get().isOwnedOrCreatedBy(user) && !user.hasRole(Role.Name.ADMIN)) { - return unauthorized("sitnet_error_access_forbidden"); + return unauthorized("i18n_error_access_forbidden"); } ExamSection form = formFactory @@ -176,7 +176,7 @@ public Result updateSection(Long eid, Long sid, Http.Request request) { section.setDescription(form.getDescription()); // Disallow changing optionality if future reservations exist if (section.isOptional() != form.isOptional() && !examUpdater.isAllowedToUpdate(section.getExam(), user)) { - return badRequest("sitnet_error_future_reservations_exist"); + return badRequest("i18n_error_future_reservations_exist"); } section.setOptional(form.isOptional()); @@ -194,9 +194,9 @@ public Result reorderSections(Long eid, Http.Request request) { int to = Integer.parseInt(df.get("to")); return checkBounds(from, to) .orElseGet(() -> { - Exam exam = Ebean.find(Exam.class).fetch("examSections").where().idEq(eid).findOne(); + Exam exam = DB.find(Exam.class).fetch("examSections").where().idEq(eid).findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (exam.isOwnedOrCreatedBy(user) || user.hasRole(Role.Name.ADMIN)) { @@ -214,7 +214,7 @@ public Result reorderSections(Long eid, Http.Request request) { } return ok(); } - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); }); } @@ -226,13 +226,13 @@ public Result reorderSectionQuestions(Long eid, Long sid, Http.Request request) int to = Integer.parseInt(df.get("to")); return checkBounds(from, to) .orElseGet(() -> { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (exam.isOwnedOrCreatedBy(user) || user.hasRole(Role.Name.ADMIN)) { - ExamSection section = Ebean.find(ExamSection.class, sid); + ExamSection section = DB.find(ExamSection.class, sid); if (section == null) { return notFound("section not found"); } @@ -250,7 +250,7 @@ public Result reorderSectionQuestions(Long eid, Long sid, Http.Request request) } return ok(); } - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); }); } @@ -275,7 +275,7 @@ private Optional insertQuestion(Exam exam, ExamSection section, Question updateSequences(section.getSectionQuestions(), sequence); sectionQuestion.setSequenceNumber(sequence); if (section.getSectionQuestions().contains(sectionQuestion) || section.hasQuestion(question)) { - return Optional.of(badRequest("sitnet_question_already_in_section")); + return Optional.of(badRequest("i18n_question_already_in_section")); } if (question.getType().equals(Question.Type.EssayQuestion)) { // disable auto evaluation for this exam @@ -284,7 +284,7 @@ private Optional insertQuestion(Exam exam, ExamSection section, Question } } - Ebean.updateAll(section.getSectionQuestions()); + DB.updateAll(section.getSectionQuestions()); // Insert new section question sectionQuestion.setCreator(user); @@ -304,18 +304,18 @@ private Optional insertQuestion(Exam exam, ExamSection section, Question @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result insertQuestion(Long eid, Long sid, Long qid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); - ExamSection section = Ebean.find(ExamSection.class, sid); - Question question = Ebean.find(Question.class, qid); + Exam exam = DB.find(Exam.class, eid); + ExamSection section = DB.find(ExamSection.class, sid); + Question question = DB.find(Question.class, qid); if (exam == null || section == null || question == null) { return notFound(); } if (exam.getAutoEvaluationConfig() != null && question.getType() == Question.Type.EssayQuestion) { - return forbidden("sitnet_error_autoevaluation_essay_question"); + return forbidden("i18n_error_autoevaluation_essay_question"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!exam.isOwnedOrCreatedBy(user) && !user.hasRole(Role.Name.ADMIN)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } Integer seq = request.body().asJson().get("sequenceNumber").asInt(); return insertQuestion(exam, section, question, user, seq).orElse(ok(section)); @@ -325,24 +325,24 @@ public Result insertQuestion(Long eid, Long sid, Long qid, Http.Request request) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Transactional public Result insertMultipleQuestions(Long eid, Long sid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); - ExamSection section = Ebean.find(ExamSection.class, sid); + Exam exam = DB.find(Exam.class, eid); + ExamSection section = DB.find(ExamSection.class, sid); if (exam == null || section == null) { return notFound(); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!exam.isOwnedOrCreatedBy(user) && !user.hasRole(Role.Name.ADMIN)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } int sequence = request.body().asJson().get("sequenceNumber").asInt(); String questions = request.body().asJson().get("questions").asText(); for (String s : questions.split(",")) { - Question question = Ebean.find(Question.class, Long.parseLong(s)); + Question question = DB.find(Question.class, Long.parseLong(s)); if (question == null) { continue; } if (exam.getAutoEvaluationConfig() != null && question.getType() == Question.Type.EssayQuestion) { - return forbidden("sitnet_error_autoevaluation_essay_question"); + return forbidden("i18n_error_autoevaluation_essay_question"); } Optional result = insertQuestion(exam, section, question, user, sequence); if (result.isPresent()) { @@ -357,7 +357,7 @@ public Result insertMultipleQuestions(Long eid, Long sid, Http.Request request) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeQuestion(Long eid, Long sid, Long qid, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExamSectionQuestion sectionQuestion = Ebean + ExamSectionQuestion sectionQuestion = DB .find(ExamSectionQuestion.class) .fetch("examSection.exam.examOwners") .fetch("question") @@ -367,12 +367,12 @@ public Result removeQuestion(Long eid, Long sid, Long qid, Http.Request request) .eq("question.id", qid) .findOne(); if (sectionQuestion == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } ExamSection section = sectionQuestion.getExamSection(); Exam exam = section.getExam(); if (!exam.isOwnedOrCreatedBy(user) && !user.hasRole(Role.Name.ADMIN)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } section.getSectionQuestions().remove(sectionQuestion); @@ -396,7 +396,7 @@ public Result removeQuestion(Long eid, Long sid, Long qid, Http.Request request) @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result clearQuestions(Long eid, Long sid, Http.Request request) { - ExamSection section = Ebean + ExamSection section = DB .find(ExamSection.class) .fetch("exam.creator") .fetch("exam.examOwners") @@ -406,7 +406,7 @@ public Result clearQuestions(Long eid, Long sid, Http.Request request) { .eq("exam.id", eid) .findOne(); if (section == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (section.getExam().isOwnedOrCreatedBy(user) || user.hasRole(Role.Name.ADMIN)) { @@ -427,7 +427,7 @@ public Result clearQuestions(Long eid, Long sid, Http.Request request) { section.update(); return ok(section); } else { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } } @@ -475,7 +475,7 @@ private void processExamQuestionOptions(Question question, ExamSectionQuestion e SanitizingHelper .parse("id", option, Long.class) .ifPresent(id -> { - ExamSectionQuestionOption esqo = Ebean.find(ExamSectionQuestionOption.class, id); + ExamSectionQuestionOption esqo = DB.find(ExamSectionQuestionOption.class, id); if (esqo != null) { esqo.setScore(round(SanitizingHelper.parse("score", option, Double.class).orElse(null))); esqo.update(); @@ -527,7 +527,7 @@ private boolean hasValidClaimChoiceOptions(ArrayNode an) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateDistributedExamQuestion(Long eid, Long sid, Long qid, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean.find(ExamSectionQuestion.class).where().idEq(qid); + ExpressionList query = DB.find(ExamSectionQuestion.class).where().idEq(qid); if (user.hasRole(Role.Name.TEACHER)) { query = query.eq("examSection.exam.examOwners", user); } @@ -535,9 +535,9 @@ public Result updateDistributedExamQuestion(Long eid, Long sid, Long qid, Http.R query.apply(pp); ExamSectionQuestion examSectionQuestion = query.findOne(); if (examSectionQuestion == null) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } - Question question = Ebean + Question question = DB .find(Question.class) .fetch("examSectionQuestions") .fetch("examSectionQuestions.options") @@ -552,14 +552,14 @@ public Result updateDistributedExamQuestion(Long eid, Long sid, Long qid, Http.R question.getType() == Question.Type.WeightedMultipleChoiceQuestion && !hasPositiveOptionScore((ArrayNode) body.get("options")) ) { - return badRequest("sitnet_correct_option_required"); + return badRequest("i18n_correct_option_required"); } if ( question.getType() == Question.Type.ClaimChoiceQuestion && !hasValidClaimChoiceOptions((ArrayNode) body.get("options")) ) { - return badRequest("sitnet_incorrect_claim_question_options"); + return badRequest("i18n_incorrect_claim_question_options"); } // Update question: text @@ -574,7 +574,7 @@ public Result updateDistributedExamQuestion(Long eid, Long sid, Long qid, Http.R // utilizing those. processExamQuestionOptions(question, examSectionQuestion, (ArrayNode) body.get("options"), user); } - // Bit dumb, refetch from database to get the updated options right in response. Could be made more elegantly + // A bit dumb, re-fetch from database to get the updated options right in response. Could be made more elegantly return ok(query.findOne(), pp); } @@ -582,7 +582,7 @@ public Result updateDistributedExamQuestion(Long eid, Long sid, Long qid, Http.R @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateUndistributedExamQuestion(Long eid, Long sid, Long qid, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean.find(ExamSectionQuestion.class).where().idEq(qid); + ExpressionList query = DB.find(ExamSectionQuestion.class).where().idEq(qid); if (user.hasRole(Role.Name.TEACHER)) { query = query.eq("examSection.exam.examOwners", user); } @@ -590,9 +590,9 @@ public Result updateUndistributedExamQuestion(Long eid, Long sid, Long qid, Http query.apply(pp); ExamSectionQuestion examSectionQuestion = query.findOne(); if (examSectionQuestion == null) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } - Question question = Ebean.find(Question.class, examSectionQuestion.getQuestion().getId()); + Question question = DB.find(Question.class, examSectionQuestion.getQuestion().getId()); if (question == null) { return notFound(); } @@ -603,7 +603,7 @@ public Result updateUndistributedExamQuestion(Long eid, Long sid, Long qid, Http @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getQuestionDistribution(Long id) { - ExamSectionQuestion esq = Ebean.find(ExamSectionQuestion.class, id); + ExamSectionQuestion esq = DB.find(ExamSectionQuestion.class, id); if (esq == null) { return notFound(); } @@ -616,4 +616,39 @@ public Result getQuestionDistribution(Long id) { node.put("distributed", isDistributed); return ok(Json.toJson(node)); } + + @Authenticated + @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) + public Result listSections( + Optional filter, + Optional> courseIds, + Optional> examIds, + Optional> tagIds, + Optional> ownerIds, + Http.Request request + ) { + User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + ExpressionList query = DB.find(ExamSection.class).where(); + if (!user.hasRole(Role.Name.ADMIN)) { + query = query.where().eq("creator.id", user.getId()); + } + if (filter.isPresent()) { + String condition = String.format("%%%s%%", filter.get()); + query = query.ilike("name", condition); + } + if (examIds.isPresent() && !examIds.get().isEmpty()) { + query = query.in("exam.id", examIds.get()); + } + if (courseIds.isPresent() && !courseIds.get().isEmpty()) { + query = query.in("exam.course.id", courseIds.get()); + } + if (tagIds.isPresent() && !tagIds.get().isEmpty()) { + query = query.in("examSectionQuestions.question.tags.id", tagIds.get()); + } + if (ownerIds.isPresent() && !ownerIds.get().isEmpty()) { + query = query.in("questionOwners.id", ownerIds.get()); + } + Set sections = query.findSet(); + return ok(sections, PathProperties.parse("(*, creator(id))")); + } } diff --git a/app/controllers/ExaminationController.java b/app/controllers/ExaminationController.java index e0c3c66d72..cae18c2d86 100644 --- a/app/controllers/ExaminationController.java +++ b/app/controllers/ExaminationController.java @@ -15,7 +15,6 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; @@ -24,7 +23,7 @@ import controllers.iop.transfer.api.ExternalAttachmentLoader; import impl.AutoEvaluationHandler; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import java.io.IOException; import java.util.HashSet; @@ -49,11 +48,13 @@ import models.questions.ClozeTestAnswer; import models.questions.EssayAnswer; import models.sections.ExamSectionQuestion; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.Environment; -import play.Logger; import play.db.ebean.Transactional; -import play.libs.concurrent.HttpExecutionContext; +import play.libs.concurrent.ClassLoaderExecutionContext; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; @@ -62,6 +63,7 @@ import sanitizers.ClozeTestAnswerSanitizer; import sanitizers.EssayAnswerSanitizer; import scala.concurrent.duration.Duration; +import scala.jdk.javaapi.CollectionConverters; import security.Authenticated; import system.interceptors.ExamActionRouter; import system.interceptors.SensitiveDataPolicy; @@ -75,14 +77,14 @@ public class ExaminationController extends BaseController { protected final EmailComposer emailComposer; protected final ExaminationRepository examinationRepository; protected final ActorSystem actor; - protected final HttpExecutionContext httpExecutionContext; + protected final ClassLoaderExecutionContext httpExecutionContext; private final AutoEvaluationHandler autoEvaluationHandler; protected final Environment environment; private final ExternalAttachmentLoader externalAttachmentLoader; private final ByodConfigHandler byodConfigHandler; protected final DateTimeHandler dateTimeHandler; - private static final Logger.ALogger logger = Logger.of(ExaminationController.class); + private final Logger logger = LoggerFactory.getLogger(ExaminationController.class); @Inject public ExaminationController( @@ -91,7 +93,7 @@ public ExaminationController( ActorSystem actor, AutoEvaluationHandler autoEvaluationHandler, Environment environment, - HttpExecutionContext httpExecutionContext, + ClassLoaderExecutionContext httpExecutionContext, ExternalAttachmentLoader externalAttachmentLoader, ByodConfigHandler byodConfigHandler, DateTimeHandler dateTimeHandler @@ -289,7 +291,7 @@ public CompletionStage turnExam(String hash, Http.Request request) { .thenApplyAsync(oe -> oe.orElseGet(() -> { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("examSections.sectionQuestions.question") .where() @@ -297,7 +299,7 @@ public CompletionStage turnExam(String hash, Http.Request request) { .eq("hash", hash) .findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Optional oep = findParticipation(exam, user); Http.Session session = request.session().removing("ongoingExamHash"); @@ -334,9 +336,9 @@ public CompletionStage abortExam(String hash, Http.Request request) { .thenApplyAsync(oe -> oe.orElseGet(() -> { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Exam exam = Ebean.find(Exam.class).where().eq("creator", user).eq("hash", hash).findOne(); + Exam exam = DB.find(Exam.class).where().eq("creator", user).eq("hash", hash).findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Optional oep = findParticipation(exam, user); Http.Session session = request.session().removing("ongoingExamHash"); @@ -365,7 +367,7 @@ public CompletionStage answerEssay(String hash, Long questionId, Http.Re oe.orElseGet(() -> { String essayAnswer = request.attrs().getOptional(Attrs.ESSAY_ANSWER).orElse(null); Optional objectVersion = request.attrs().getOptional(Attrs.OBJECT_VERSION); - ExamSectionQuestion question = Ebean.find(ExamSectionQuestion.class, questionId); + ExamSectionQuestion question = DB.find(ExamSectionQuestion.class, questionId); if (question == null) { return forbidden(); } @@ -394,8 +396,8 @@ public CompletionStage answerMultiChoice(String hash, Long qid, Http.Req List optionIds = StreamSupport .stream(node.spliterator(), false) .map(JsonNode::asLong) - .collect(Collectors.toList()); - ExamSectionQuestion question = Ebean.find(ExamSectionQuestion.class, qid); + .toList(); + ExamSectionQuestion question = DB.find(ExamSectionQuestion.class, qid); if (question == null) { return forbidden(); } @@ -417,7 +419,7 @@ public CompletionStage answerClozeTest(String hash, Long questionId, Htt return getEnrolmentError(hash, request) .thenApplyAsync(oe -> oe.orElseGet(() -> { - ExamSectionQuestion esq = Ebean.find(ExamSectionQuestion.class, questionId); + ExamSectionQuestion esq = DB.find(ExamSectionQuestion.class, questionId); if (esq == null) { return forbidden(); } @@ -436,7 +438,7 @@ public CompletionStage answerClozeTest(String hash, Long questionId, Htt } private Optional findParticipation(Exam exam, User user) { - return Ebean + return DB .find(ExamParticipation.class) .where() .eq("exam.id", exam.getId()) @@ -463,7 +465,7 @@ protected CompletionStage> getEnrolmentError(ExamEnrolment enro // If this is null, it means someone is either trying to access an exam by wrong hash // or the reservation is not in effect right now. if (enrolment == null) { - return CompletableFuture.completedFuture(Optional.of(forbidden("sitnet_reservation_not_found"))); + return CompletableFuture.completedFuture(Optional.of(forbidden("i18n_reservation_not_found"))); } Exam exam = enrolment.getExam(); boolean isByod = exam != null && exam.getImplementation() == Exam.Implementation.CLIENT_AUTH; @@ -475,9 +477,9 @@ protected CompletionStage> getEnrolmentError(ExamEnrolment enro } else if (isUnchecked) { return CompletableFuture.completedFuture(Optional.empty()); } else if (enrolment.getReservation() == null) { - return CompletableFuture.completedFuture(Optional.of(forbidden("sitnet_reservation_not_found"))); + return CompletableFuture.completedFuture(Optional.of(forbidden("i18n_reservation_not_found"))); } else if (enrolment.getReservation().getMachine() == null) { - return CompletableFuture.completedFuture(Optional.of(forbidden("sitnet_reservation_machine_not_found"))); + return CompletableFuture.completedFuture(Optional.of(forbidden("i18n_reservation_machine_not_found"))); } else if ( !environment.isDev() && !enrolment.getReservation().getMachine().getIpAddress().equals(request.remoteAddress()) @@ -491,11 +493,11 @@ protected CompletionStage> getEnrolmentError(ExamEnrolment enro } ExamRoom room = or.get(); String message = - "sitnet_wrong_exam_machine " + + "i18n_wrong_exam_machine " + room.getName() + ", " + room.getMailAddress().toString() + - ", sitnet_exam_machine " + + ", i18n_exam_machine " + enrolment.getReservation().getMachine().getName(); return Optional.of(forbidden(message)); }, @@ -508,7 +510,7 @@ protected CompletionStage> getEnrolmentError(ExamEnrolment enro public static PathProperties getPath(boolean includeEnrolment) { String path = "(id, name, state, instruction, hash, duration, cloned, external, implementation, " + - "course(id, code, name), executionType(id, type), " + // ( + "course(id, code, name), examType(id, type), executionType(id, type), " + // ( "examParticipation(id), " + // "examLanguages(code), attachment(fileName), examOwners(firstName, lastName)" + "examInspections(*, user(id, firstName, lastName))" + @@ -525,7 +527,7 @@ public static PathProperties getPath(boolean includeEnrolment) { private CompletionStage> getEnrolmentError(String hash, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .eq("exam.hash", hash) @@ -543,7 +545,12 @@ private void notifyTeachers(Exam exam) { .scheduler() .scheduleOnce( Duration.create(1, TimeUnit.SECONDS), - () -> AppUtil.notifyPrivateExamEnded(recipients, exam, emailComposer), + () -> + AppUtil.notifyPrivateExamEnded( + CollectionConverters.asScala(recipients).toSet(), + exam, + emailComposer + ), actor.dispatcher() ); } diff --git a/app/controllers/ExaminationEventController.java b/app/controllers/ExaminationEventController.java index e31149080e..64416f3df9 100644 --- a/app/controllers/ExaminationEventController.java +++ b/app/controllers/ExaminationEventController.java @@ -18,12 +18,13 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.text.PathProperties; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import javax.inject.Inject; import models.Exam; import models.ExaminationDate; @@ -34,7 +35,8 @@ import org.joda.time.Interval; import org.joda.time.LocalDate; import org.joda.time.format.ISODateTimeFormat; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; @@ -46,7 +48,7 @@ public class ExaminationEventController extends BaseController { - private static final Logger.ALogger logger = Logger.of(ExaminationEventController.class); + private final Logger logger = LoggerFactory.getLogger(ExaminationEventController.class); @Inject ByodConfigHandler byodConfigHandler; @@ -58,7 +60,7 @@ public class ExaminationEventController extends BaseController { @With(ExaminationDateSanitizer.class) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result insertExaminationDate(Long eid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { return notFound("exam not found"); } @@ -72,7 +74,7 @@ public Result insertExaminationDate(Long eid, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeExaminationDate(Long id, Long edid) { - ExaminationDate ed = Ebean.find(ExaminationDate.class, edid); + ExaminationDate ed = DB.find(ExaminationDate.class, edid); if (ed == null) { return notFound("examination date not found"); } @@ -90,7 +92,7 @@ private DateTime getEventEnding(ExaminationEvent ee) { } private int getParticipantUpperBound(DateTime start, DateTime end, Long id) { - ExpressionList el = Ebean.find(ExaminationEvent.class).where().le("start", end); + ExpressionList el = DB.find(ExaminationEvent.class).where().le("start", end); if (id != null) { el = el.ne("id", id); } @@ -103,7 +105,7 @@ private int getParticipantUpperBound(DateTime start, DateTime end, Long id) { } private boolean isWithinMaintenancePeriod(Interval interval) { - return Ebean + return DB .find(MaintenancePeriod.class) .findSet() .stream() @@ -114,7 +116,7 @@ private boolean isWithinMaintenancePeriod(Interval interval) { @With(ExaminationEventSanitizer.class) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result insertExaminationEvent(Long eid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { return notFound("exam not found"); } @@ -124,20 +126,24 @@ public Result insertExaminationEvent(Long eid, Http.Request request) { ExaminationEvent ee = new ExaminationEvent(); DateTime start = request.attrs().get(Attrs.START_DATE); if (start.isBeforeNow()) { - return forbidden("sitnet_error_examination_event_in_the_past"); + return forbidden("i18n_error_examination_event_in_the_past"); } DateTime end = start.plusMinutes(exam.getDuration()); if (isWithinMaintenancePeriod(new Interval(start, end))) { - return forbidden("sitnet_error_conflicts_with_maintenance_period"); + return forbidden("i18n_error_conflicts_with_maintenance_period"); } int ub = getParticipantUpperBound(start, end, null); int capacity = request.attrs().get(Attrs.CAPACITY); if (capacity + ub > configReader.getMaxByodExaminationParticipantCount()) { - return forbidden("sitnet_error_max_capacity_exceeded"); + return forbidden("i18n_error_max_capacity_exceeded"); } - String password = request.attrs().get(Attrs.SETTINGS_PASSWORD); - if (exam.getImplementation() == Exam.Implementation.CLIENT_AUTH && password == null) { - return forbidden("no password provided"); + String quitPassword = request.attrs().get(Attrs.QUIT_PASSWORD); + if (exam.getImplementation() == Exam.Implementation.CLIENT_AUTH && quitPassword == null) { + return forbidden("no quit password provided"); + } + String settingsPassword = request.attrs().get(Attrs.SETTINGS_PASSWORD); + if (exam.getImplementation() == Exam.Implementation.CLIENT_AUTH && settingsPassword == null) { + return forbidden("no settings password provided"); } ee.setStart(start); ee.setDescription(request.attrs().get(Attrs.DESCRIPTION)); @@ -146,20 +152,22 @@ public Result insertExaminationEvent(Long eid, Http.Request request) { eec.setExaminationEvent(ee); eec.setExam(exam); eec.setHash(UUID.randomUUID().toString()); - if (password != null) { - encryptSettingsPassword(eec, password); + if (quitPassword != null && settingsPassword != null) { + encryptQuitPassword(eec, quitPassword); + encryptSettingsPassword(eec, settingsPassword, quitPassword); + // Pass back the plaintext password, so it can be shown to user + eec.setQuitPassword(quitPassword); + eec.setSettingsPassword(settingsPassword); } eec.save(); - // Pass back the plaintext password, so it can be shown to user - eec.setSettingsPassword(request.attrs().get(Attrs.SETTINGS_PASSWORD)); return ok(eec); } @With(ExaminationEventSanitizer.class) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateExaminationEvent(Long eid, Long eecid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); - Optional oeec = Ebean + Exam exam = DB.find(Exam.class, eid); + Optional oeec = DB .find(ExaminationEventConfiguration.class) .where() .idEq(eecid) @@ -169,43 +177,51 @@ public Result updateExaminationEvent(Long eid, Long eecid, Http.Request request) return notFound("event not found"); } ExaminationEventConfiguration eec = oeec.get(); - boolean hasEnrolments = eec.getExamEnrolments().size() > 0; + boolean hasEnrolments = !eec.getExamEnrolments().isEmpty(); ExaminationEvent ee = eec.getExaminationEvent(); - String password = request.attrs().get(Attrs.SETTINGS_PASSWORD); - if (eec.getExam().getImplementation() == Exam.Implementation.CLIENT_AUTH && password == null) { - return forbidden("no password provided"); + String quitPassword = request.attrs().get(Attrs.QUIT_PASSWORD); + if (eec.getExam().getImplementation() == Exam.Implementation.CLIENT_AUTH && quitPassword == null) { + return forbidden("no quit password provided"); + } + String settingsPassword = request.attrs().get(Attrs.SETTINGS_PASSWORD); + if (eec.getExam().getImplementation() == Exam.Implementation.CLIENT_AUTH && settingsPassword == null) { + return forbidden("no settings password provided"); } DateTime start = request.attrs().get(Attrs.START_DATE); if (!hasEnrolments) { if (start.isBeforeNow()) { - return forbidden("sitnet_error_examination_event_in_the_past"); + return forbidden("i18n_error_examination_event_in_the_past"); } ee.setStart(start); } DateTime end = start.plusMinutes(exam.getDuration()); if (isWithinMaintenancePeriod(new Interval(start, end))) { - return forbidden("sitnet_error_conflicts_with_maintenance_period"); + return forbidden("i18n_error_conflicts_with_maintenance_period"); } int ub = getParticipantUpperBound(start, end, ee.getId()); int capacity = request.attrs().get(Attrs.CAPACITY); if (capacity + ub > configReader.getMaxByodExaminationParticipantCount()) { - return forbidden("sitnet_error_max_capacity_exceeded"); + return forbidden("i18n_error_max_capacity_exceeded"); } ee.setCapacity(capacity); ee.setDescription(request.attrs().get(Attrs.DESCRIPTION)); - ee.update(); - if (password == null) { + if (quitPassword == null || settingsPassword == null) { return ok(eec); - } else if (!hasEnrolments) { - encryptSettingsPassword(eec, password); + } + if (!hasEnrolments) { + encryptQuitPassword(eec, quitPassword); + encryptSettingsPassword(eec, settingsPassword, quitPassword); eec.save(); - // Pass back the plaintext password, so it can be shown to user - eec.setSettingsPassword(request.attrs().get(Attrs.SETTINGS_PASSWORD)); + // Pass back the plaintext passwords, so they can be shown to user + eec.setQuitPassword(quitPassword); + eec.setSettingsPassword(settingsPassword); } else { // Disallow changing password if enrolments exist for this event - // TODO: check how this could be made possible. Would need resending seb-files with new encryption - // Send back the original (unchanged password) + // Pass back the original unchanged passwords + eec.setQuitPassword( + byodConfigHandler.getPlaintextPassword(eec.getEncryptedQuitPassword(), eec.getQuitPasswordSalt()) + ); eec.setSettingsPassword( byodConfigHandler.getPlaintextPassword( eec.getEncryptedSettingsPassword(), @@ -218,13 +234,13 @@ public Result updateExaminationEvent(Long eid, Long eecid, Http.Request request) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result removeExaminationEvent(Long eid, Long eeid) { - Optional oeec = Ebean + Optional oeec = DB .find(ExaminationEventConfiguration.class) .where() .idEq(eeid) .eq("exam.id", eid) .findOneOrEmpty(); - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (oeec.isEmpty() || exam == null) { return notFound("event not found"); } @@ -234,7 +250,7 @@ public Result removeExaminationEvent(Long eid, Long eeid) { } eec.delete(); // Check if we can delete the event altogether (in case no configs are using it) - Set configs = Ebean + Set configs = DB .find(ExaminationEventConfiguration.class) .where() .eq("examinationEvent", eec.getExaminationEvent()) @@ -245,7 +261,7 @@ public Result removeExaminationEvent(Long eid, Long eeid) { return ok(); } - private void encryptSettingsPassword(ExaminationEventConfiguration eec, String password) { + private void encryptSettingsPassword(ExaminationEventConfiguration eec, String password, String quitPassword) { try { String oldPwd = eec.getEncryptedSettingsPassword() != null ? byodConfigHandler.getPlaintextPassword( @@ -259,7 +275,26 @@ private void encryptSettingsPassword(ExaminationEventConfiguration eec, String p eec.setEncryptedSettingsPassword(byodConfigHandler.getEncryptedPassword(password, newSalt)); eec.setSettingsPasswordSalt(newSalt); // Pre-calculate config key, so we don't need to do it each time a check is needed - eec.setConfigKey(byodConfigHandler.calculateConfigKey(eec.getHash())); + eec.setConfigKey(byodConfigHandler.calculateConfigKey(eec.getHash(), quitPassword)); + } + } catch (Exception e) { + logger.error("unable to set settings password", e); + throw new RuntimeException(e); + } + } + + private void encryptQuitPassword(ExaminationEventConfiguration eec, String password) { + try { + String oldPwd = eec.getEncryptedQuitPassword() != null + ? byodConfigHandler.getPlaintextPassword(eec.getEncryptedQuitPassword(), eec.getQuitPasswordSalt()) + : null; + + if (!password.equals(oldPwd)) { + String newSalt = UUID.randomUUID().toString(); + eec.setEncryptedQuitPassword(byodConfigHandler.getEncryptedPassword(password, newSalt)); + eec.setQuitPasswordSalt(newSalt); + // Pre-calculate config key, so we don't need to do it each time a check is needed + eec.setConfigKey(byodConfigHandler.calculateConfigKey(eec.getHash(), password)); } } catch (Exception e) { logger.error("unable to set settings password", e); @@ -272,7 +307,7 @@ public Result listExaminationEvents(Optional start, Optional end PathProperties pp = PathProperties.parse( "(*, exam(*, course(*), examOwners(*)), examinationEvent(*), examEnrolments(*))" ); - ExpressionList query = Ebean + ExpressionList query = DB .find(ExaminationEventConfiguration.class) .apply(pp) .where(); @@ -287,4 +322,20 @@ public Result listExaminationEvents(Optional start, Optional end Set exams = query.where().eq("exam.state", Exam.State.PUBLISHED).findSet(); return ok(exams, pp); } + + @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) + public Result listOverlappingExaminationEvents(String start, Integer duration) { + PathProperties pp = PathProperties.parse("(*, examinationEventConfiguration(exam(id, duration)))"); + DateTime startDate = DateTime.parse(start, ISODateTimeFormat.dateTimeParser()); + DateTime endDate = startDate.plusMinutes(duration); + Set events = DB + .find(ExaminationEvent.class) + .where() + .le("start", endDate) + .findSet() + .stream() + .filter(ee -> !getEventEnding(ee).isBefore(startDate)) + .collect(Collectors.toSet()); + return ok(events, pp); + } } diff --git a/app/controllers/LanguageController.java b/app/controllers/LanguageController.java index b5ef2e3b3f..718e53e93c 100644 --- a/app/controllers/LanguageController.java +++ b/app/controllers/LanguageController.java @@ -18,7 +18,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.List; import models.Language; import play.libs.Json; @@ -28,7 +28,7 @@ public class LanguageController extends BaseController { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getSupportedLanguages() { - List languages = Ebean.find(Language.class).findList(); + List languages = DB.find(Language.class).findList(); return ok(Json.toJson(languages)); } } diff --git a/app/controllers/LanguageInspectionController.java b/app/controllers/LanguageInspectionController.java index 39e19a50d2..a30c25e722 100644 --- a/app/controllers/LanguageInspectionController.java +++ b/app/controllers/LanguageInspectionController.java @@ -15,14 +15,13 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Dynamic; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Pattern; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.FetchConfig; import java.net.URLDecoder; @@ -36,8 +35,10 @@ import models.Exam; import models.LanguageInspection; import models.User; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.data.DynamicForm; import play.mvc.Http; import play.mvc.Result; @@ -55,17 +56,17 @@ public class LanguageInspectionController extends BaseController { @Inject protected ActorSystem actor; - private static final Logger.ALogger logger = Logger.of(LanguageInspectionController.class); + private final Logger logger = LoggerFactory.getLogger(LanguageInspectionController.class); @Dynamic(value = "inspector or admin", meta = "pattern=CAN_INSPECT_LANGUAGE,role=ADMIN,anyMatch=true") public Result listInspections(Optional month, Optional start, Optional end) { - ExpressionList query = Ebean + ExpressionList query = DB .find(LanguageInspection.class) .fetch("exam") .fetch("exam.course") .fetch("exam.creator", "firstName, lastName, email, userIdentifier") .fetch("exam.parent.examOwners", "firstName, lastName, email, userIdentifier") - .fetch("exam.examLanguages", new FetchConfig().query()) + .fetch("exam.examLanguages", FetchConfig.ofQuery()) .fetch("statement") .fetch("creator", "firstName, lastName, email, userIdentifier") .fetch("assignee", "firstName, lastName, email, userIdentifier") @@ -97,9 +98,9 @@ public Result listInspections(Optional month, Optional start, Opti public Result createInspection(Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); Long examId = Long.parseLong(df.get("examId")); - Exam exam = Ebean.find(Exam.class, examId); + Exam exam = DB.find(Exam.class, examId); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } if (exam.getLanguageInspection() != null) { return forbidden("already sent for inspection"); @@ -118,7 +119,7 @@ public Result createInspection(Http.Request request) { @Authenticated @Pattern(value = "CAN_INSPECT_LANGUAGE") public Result assignInspection(Long id, Http.Request request) { - LanguageInspection inspection = Ebean.find(LanguageInspection.class, id); + LanguageInspection inspection = DB.find(LanguageInspection.class, id); if (inspection == null) { return notFound("Inspection not found"); } @@ -134,9 +135,6 @@ public Result assignInspection(Long id, Http.Request request) { } private Optional checkInspection(LanguageInspection inspection) { - if (inspection == null) { - return Optional.of(notFound("Inspection not found")); - } if (inspection.getStartedAt() == null) { return Optional.of(forbidden("Inspection not assigned")); } @@ -151,14 +149,13 @@ private Optional checkInspection(LanguageInspection inspection) { public Result setApproval(Long id, Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); boolean isApproved = Boolean.parseBoolean(df.get("approved")); - LanguageInspection inspection = Ebean.find(LanguageInspection.class, id); + LanguageInspection inspection = DB.find(LanguageInspection.class, id); + if (inspection == null) { + return notFound("Inspection not found"); + } return checkInspection(inspection) .orElseGet(() -> { - if ( - inspection == null || - inspection.getStatement() == null || - inspection.getStatement().getComment().isEmpty() - ) { + if (inspection.getStatement() == null || inspection.getStatement().getComment().isEmpty()) { return forbidden("No statement given"); } inspection.setFinishedAt(new Date()); @@ -194,7 +191,10 @@ public Result setStatement(Long id, Http.Request request) { if (text.isEmpty()) { return badRequest(); } - LanguageInspection inspection = Ebean.find(LanguageInspection.class, id); + LanguageInspection inspection = DB.find(LanguageInspection.class, id); + if (inspection == null) { + return notFound("Inspection not found"); + } return checkInspection(inspection) .orElseGet(() -> { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); diff --git a/app/controllers/MaintenancePeriodController.java b/app/controllers/MaintenancePeriodController.java deleted file mode 100644 index ad1b9b2b47..0000000000 --- a/app/controllers/MaintenancePeriodController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package controllers; - -import be.objectify.deadbolt.java.actions.Group; -import be.objectify.deadbolt.java.actions.Restrict; -import com.fasterxml.jackson.databind.JsonNode; -import controllers.base.BaseController; -import io.ebean.Ebean; -import java.util.List; -import models.calendar.MaintenancePeriod; -import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; -import play.mvc.Http; -import play.mvc.Result; - -public class MaintenancePeriodController extends BaseController { - - @Restrict({ @Group("TEACHER"), @Group("ADMIN"), @Group("STUDENT") }) - public Result listMaintenancePeriods() { - List periods = Ebean - .find(MaintenancePeriod.class) - .where() - .gt("endsAt", DateTime.now()) - .findList(); - return ok(periods); - } - - @Restrict({ @Group("ADMIN") }) - public Result createMaintenancePeriod(Http.Request request) { - JsonNode body = request.body().asJson(); - DateTime start = DateTime.parse(body.get("startsAt").asText(), ISODateTimeFormat.dateTimeParser()); - DateTime end = DateTime.parse(body.get("endsAt").asText(), ISODateTimeFormat.dateTimeParser()); - String description = body.get("description").asText(); - MaintenancePeriod period = new MaintenancePeriod(); - period.setStartsAt(start); - period.setEndsAt(end); - period.setDescription(description); - period.save(); - return created(period); - } - - @Restrict({ @Group("ADMIN") }) - public Result updateMaintenancePeriod(Long id, Http.Request request) { - MaintenancePeriod period = Ebean.find(MaintenancePeriod.class, id); - if (period == null) { - return notFound(); - } - JsonNode body = request.body().asJson(); - DateTime start = DateTime.parse(body.get("startsAt").asText(), ISODateTimeFormat.dateTimeParser()); - DateTime end = DateTime.parse(body.get("endsAt").asText(), ISODateTimeFormat.dateTimeParser()); - String description = body.get("description").asText(); - period.setStartsAt(start); - period.setEndsAt(end); - period.setDescription(description); - period.update(); - return ok(); - } - - @Restrict({ @Group("ADMIN") }) - public Result removeMaintenancePeriod(Long id) { - MaintenancePeriod period = Ebean.find(MaintenancePeriod.class, id); - if (period == null) { - return notFound(); - } - period.delete(); - return ok(); - } -} diff --git a/app/controllers/MaintenancePeriodController.scala b/app/controllers/MaintenancePeriodController.scala new file mode 100644 index 0000000000..0c945c3553 --- /dev/null +++ b/app/controllers/MaintenancePeriodController.scala @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and limitations under the Licence. + */ + +package controllers + +import io.ebean.DB +import models.Role +import models.calendar.MaintenancePeriod +import org.joda.time.DateTime +import org.joda.time.format.ISODateTimeFormat +import play.api.libs.json.JsValue +import play.api.mvc.* +import security.scala.Auth.authorized +import security.scala.AuthExecutionContext +import system.AuditedAction +import util.scala.{DbApiHelper, JavaApiHelper} + +import javax.inject.Inject + +class MaintenancePeriodController @Inject() ( + val controllerComponents: ControllerComponents, + val audited: AuditedAction, + implicit val ec: AuthExecutionContext +) extends BaseController + with DbApiHelper + with JavaApiHelper: + + def listMaintenancePeriods: Action[AnyContent] = + Action.andThen(authorized(Seq(Role.Name.STUDENT, Role.Name.TEACHER, Role.Name.ADMIN))).andThen(audited) { _ => + DB.find(classOf[MaintenancePeriod]) + .where() + .gt("endsAt", DateTime.now()) + .list + .toResult(Results.Ok) + } + + def createMaintenancePeriod: Action[AnyContent] = + Action.andThen(authorized(Seq(Role.Name.ADMIN))).andThen(audited) { request => + request.body.asJson match + case Some(body) => + parseBody(body) match + case (Some(s), Some(e), Some(d)) => + val period = update(new MaintenancePeriod, s, e, d) + period.save() + period.toResult(Results.Created) + case _ => BadRequest + case _ => BadRequest + } + + def updateMaintenancePeriod(id: Long): Action[AnyContent] = + Action.andThen(authorized(Seq(Role.Name.ADMIN))).andThen(audited) { request => + request.body.asJson match + case Some(body) => + DB.find(classOf[MaintenancePeriod]).where().idEq(id).find match + case Some(mp) => + parseBody(body) match + case (Some(s), Some(e), Some(d)) => + val period = update(mp, s, e, d) + period.update() + Ok + case _ => BadRequest + case _ => NotFound + case _ => BadRequest + } + + def removeMaintenancePeriod(id: Long): Action[AnyContent] = + Action.andThen(authorized(Seq(Role.Name.ADMIN))).andThen(audited) { _ => + DB.find(classOf[MaintenancePeriod]).where().idEq(id).find match + case Some(mp) => + mp.delete() + Ok + case _ => NotFound + } + + private def parseBody(body: JsValue) = + def parseDate(d: String) = DateTime.parse(d, ISODateTimeFormat.dateTimeParser()) + val start = (body \ "startsAt").asOpt[String].map(parseDate) + val end = (body \ "endsAt").asOpt[String].map(parseDate) + val description = (body \ "description").asOpt[String] + (start, end, description) + + private def update(period: MaintenancePeriod, start: DateTime, end: DateTime, description: String) = + period.setStartsAt(start) + period.setEndsAt(end) + period.setDescription(description) + period diff --git a/app/controllers/QuestionController.java b/app/controllers/QuestionController.java index 9053a18a38..6e86202e9b 100644 --- a/app/controllers/QuestionController.java +++ b/app/controllers/QuestionController.java @@ -21,11 +21,12 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import controllers.base.BaseController; import controllers.base.SectionQuestionHandler; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.Model; import io.ebean.Query; import io.ebean.text.PathProperties; +import jakarta.persistence.PersistenceException; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -35,14 +36,17 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.inject.Inject; -import javax.persistence.PersistenceException; import models.Exam; import models.Role; import models.Tag; import models.User; +import models.questions.ClozeTestAnswer; import models.questions.MultipleChoiceOption; import models.questions.Question; -import play.Logger; +import models.sections.ExamSectionQuestion; +import models.sections.ExamSectionQuestionOption; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.data.DynamicForm; import play.libs.Files; import play.mvc.BodyParser; @@ -65,7 +69,7 @@ public class QuestionController extends BaseController implements SectionQuestio @Inject private MoodleXmlImporter xmlImporter; - private static final Logger.ALogger logger = Logger.of(QuestionController.class); + private final Logger logger = LoggerFactory.getLogger(QuestionController.class); private enum QuestionState { NEW, @@ -80,19 +84,21 @@ public Result getQuestions( List courseIds, List tagIds, List sectionIds, + List ownerIds, Http.Request request ) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if ( - user.hasRole(Role.Name.ADMIN) && Stream.of(examIds, courseIds, tagIds, sectionIds).allMatch(List::isEmpty) + user.hasRole(Role.Name.ADMIN) && + Stream.of(examIds, courseIds, tagIds, sectionIds, ownerIds).allMatch(List::isEmpty) ) { return ok(Collections.emptySet()); } PathProperties pp = PathProperties.parse( - "*, modifier(firstName, lastName) questionOwners(id, firstName, lastName, userIdentifier, email), " + - "attachment(id, fileName), options(defaultScore, correctOption, claimChoiceType), tags(name), examSectionQuestions(examSection(exam(state, examActiveEndDate, course(code)))))" + "*, modifier(firstName, lastName), questionOwners(id, firstName, lastName, userIdentifier, email), " + + "attachment(id, fileName), options(defaultScore, correctOption, claimChoiceType), tags(id, name, creator(id)), examSectionQuestions(examSection(exam(state, periodEnd, course(code)))))" ); - Query query = Ebean.find(Question.class); + Query query = DB.find(Question.class); pp.apply(query); ExpressionList el = query .where() @@ -100,21 +106,27 @@ public Result getQuestions( .endJunction() .ne("state", QuestionState.DELETED.toString()); if (user.hasRole(Role.Name.TEACHER)) { - el = el.disjunction().eq("shared", true).eq("questionOwners", user).endJunction(); - } - if (!examIds.isEmpty()) { - el = el.in("examSectionQuestions.examSection.exam.id", examIds); - } - if (!courseIds.isEmpty()) { - el = el.in("examSectionQuestions.examSection.exam.course.id", courseIds); - } - if (!tagIds.isEmpty()) { - el = el.in("tags.id", tagIds); - } - if (!sectionIds.isEmpty()) { - el = el.in("examSectionQuestions.examSection.id", sectionIds); + if (ownerIds.isEmpty()) { + el = el.eq("questionOwners", user); + } else { + el = el.in("questionOwners.id", ownerIds); + } + } else { + el = el.inOrEmpty("questionOwners.id", ownerIds); } + el = el.inOrEmpty("examSectionQuestions.examSection.exam.id", examIds); + el = el.inOrEmpty("examSectionQuestions.examSection.exam.course.id", courseIds); + el = el.inOrEmpty("tags.id", tagIds); + el = el.inOrEmpty("examSectionQuestions.examSection.id", sectionIds); + Set questions = el.orderBy("created desc").findSet(); + if (user.hasRole(Role.Name.TEACHER) && !ownerIds.isEmpty()) { + questions = + questions + .stream() + .filter(question -> question.getQuestionOwners().contains(user)) + .collect(Collectors.toSet()); + } return ok(questions, pp); } @@ -135,10 +147,10 @@ private Optional getQuestionOfUser(ExpressionList expr, User @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getQuestion(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Query query = Ebean.find(Question.class); + Query query = DB.find(Question.class); PathProperties pp = PathProperties.parse( "(*, questionOwners(id, firstName, lastName, userIdentifier, email), " + - "attachment(id, fileName), options(id, correctOption, defaultScore, option, claimChoiceType), tags(id, name), " + + "attachment(id, fileName), options(id, correctOption, defaultScore, option, claimChoiceType), tags(id, name, creator(id)), " + "examSectionQuestions(id, examSection(name, exam(name, state))))" ); pp.apply(query); @@ -149,7 +161,7 @@ public Result getQuestion(Long id, Http.Request request) { Collections.sort(q.getOptions()); return ok(q, pp); } else { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } } @@ -157,13 +169,13 @@ public Result getQuestion(Long id, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result copyQuestion(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean.find(Question.class).fetch("questionOwners").where().idEq(id); + ExpressionList query = DB.find(Question.class).fetch("questionOwners").where().idEq(id); if (user.hasRole(Role.Name.TEACHER)) { query = query.disjunction().eq("shared", true).eq("questionOwners", user).endJunction(); } Question question = query.findOne(); if (question == null) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } Collections.sort(question.getOptions()); Question copy = question.copy(); @@ -176,7 +188,7 @@ public Result copyQuestion(Long id, Http.Request request) { copy.getQuestionOwners().clear(); copy.getQuestionOwners().add(user); copy.update(); - Ebean.saveAll(copy.getOptions()); + DB.saveAll(copy.getOptions()); return ok(copy); } @@ -214,7 +226,7 @@ private Question parseFromBody(Http.Request request, User user, Question existin question.getQuestionOwners().clear(); if (node.has("questionOwners")) { for (JsonNode ownerNode : node.get("questionOwners")) { - User owner = Ebean.find(User.class, ownerNode.get("id").asLong()); + User owner = DB.find(User.class, ownerNode.get("id").asLong()); if (owner != null) { question.getQuestionOwners().add(owner); } @@ -226,21 +238,21 @@ private Question parseFromBody(Http.Request request, User user, Question existin // See if we have an identical tag already and use it if that's the case Optional tag = Optional.empty(); if (tagNode.has("id")) { - tag = Ebean.find(Tag.class).where().idEq(tagNode.get("id").asLong()).findOneOrEmpty(); + tag = DB.find(Tag.class).where().idEq(tagNode.get("id").asLong()).findOneOrEmpty(); } else { - List tags = Ebean + List tags = DB .find(Tag.class) .where() .eq("name", tagNode.get("name").asText()) .eq("creator", user) .findList(); if (!tags.isEmpty()) { - tag = Optional.of(tags.get(0)); + tag = Optional.of(tags.getFirst()); } } if (tag.isEmpty()) { Tag newTag = new Tag(); - newTag.setName(tagNode.get("name").asText()); + newTag.setName(tagNode.get("name").asText().toLowerCase()); newTag.setCreatorWithDate(user); newTag.setModifier(user); tag = Optional.of(newTag); @@ -277,7 +289,7 @@ public Result createQuestion(Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateQuestion(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean.find(Question.class).where().idEq(id); + ExpressionList query = DB.find(Question.class).where().idEq(id); if (user.hasRole(Role.Name.TEACHER)) { query = query @@ -289,7 +301,7 @@ public Result updateQuestion(Long id, Http.Request request) { } Question question = query.findOne(); if (question == null) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } Question updatedQuestion = parseFromBody(request, user, question); JsonNode body = request.body().asJson(); @@ -308,7 +320,7 @@ public Result updateQuestion(Long id, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result deleteQuestion(Long id, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList expr = Ebean.find(Question.class).where().idEq(id); + ExpressionList expr = DB.find(Question.class).where().idEq(id); if (user.hasRole(Role.Name.TEACHER)) { expr = expr.disjunction().eq("shared", true).eq("questionOwners", user).endJunction(); } @@ -324,7 +336,7 @@ public Result deleteQuestion(Long id, Http.Request request) { .stream() .anyMatch(esq -> { Exam exam = esq.getExamSection().getExam(); - return (exam.getState() == Exam.State.PUBLISHED && exam.getExamActiveEndDate().isAfterNow()); + return (exam.getState() == Exam.State.PUBLISHED && exam.getPeriodEnd().isAfterNow()); }) ) { return forbidden(); @@ -393,7 +405,7 @@ private void createOption(Question question, JsonNode node, User user) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result addOwner(Long uid, Http.Request request) { - User newOwner = Ebean + User newOwner = DB .find(User.class) .select("id, firstName, lastName, userIdentifier") .where() @@ -408,9 +420,9 @@ public Result addOwner(Long uid, Http.Request request) { if (questionIds == null || questionIds.isEmpty()) { return badRequest(); } - List ids = Stream.of(questionIds.split(",")).map(Long::parseLong).collect(Collectors.toList()); + List ids = Stream.of(questionIds.split(",")).map(Long::parseLong).toList(); User modifier = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList expr = Ebean.find(Question.class).where().idIn(ids); + ExpressionList expr = DB.find(Question.class).where().idIn(ids); if (modifier.hasRole(Role.Name.TEACHER)) { expr = expr.disjunction().eq("shared", true).eq("questionOwners", modifier).endJunction(); } @@ -436,7 +448,7 @@ public Result exportQuestions(Http.Request request) { .stream(node.spliterator(), false) .map(JsonNode::asLong) .collect(Collectors.toSet()); - List questions = Ebean + List questions = DB .find(Question.class) .where() .idIn(ids) @@ -445,7 +457,7 @@ public Result exportQuestions(Http.Request request) { .filter(q -> q.getType() != Question.Type.ClaimChoiceQuestion && q.getType() != Question.Type.ClozeTestQuestion ) - .collect(Collectors.toList()); + .toList(); String document = xmlExporter.convert(CollectionConverters.asScala(questions).toSeq()); return ok(document) .withHeader("Content-Disposition", "attachment; filename=\"moodle-quiz.xml\"") @@ -464,4 +476,79 @@ public Result importQuestions(Http.Request request) throws IOException { xmlImporter.convert(content, request.attrs().get(Attrs.AUTHENTICATED_USER)); return ok(); } + + private Result processPreview(ExamSectionQuestion esq) { + if (esq.getQuestion().getType() == Question.Type.ClozeTestQuestion) { + ClozeTestAnswer answer = new ClozeTestAnswer(); + answer.setQuestion(esq); + esq.setClozeTestAnswer(answer); + } + + esq.setDerivedMaxScore(); + if (esq.getQuestion().getType() == Question.Type.ClaimChoiceQuestion) { + esq.setDerivedMinScore(); + } + if (esq.getQuestion().getType() == Question.Type.ClozeTestQuestion) { + esq.getQuestion().setQuestion(null); + } + return ok(esq); + } + + @Authenticated + @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) + public Result getQuestionPreview(Long qid, Http.Request request) { + User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + ExpressionList el = DB + .find(Question.class) + .fetch("attachment", "fileName") + .fetch("options") + .where() + .idEq(qid); + if (user.hasRole(Role.Name.TEACHER)) { + el = el.eq("questionOwners", user); + } + return el + .findOneOrEmpty() + .map(question -> { + // Produce fake exam section question based on base question + List esqos = question + .getOptions() + .stream() + .map(o -> { + ExamSectionQuestionOption esqo = new ExamSectionQuestionOption(); + esqo.setId(1L); + esqo.setOption(o); + esqo.setScore(o.getDefaultScore()); + return esqo; + }) + .toList(); + ExamSectionQuestion esq = new ExamSectionQuestion(); + esq.setOptions(Set.copyOf(esqos)); + esq.setQuestion(question); + esq.setAnswerInstructions(question.getDefaultAnswerInstructions()); + esq.setEvaluationCriteria(question.getDefaultEvaluationCriteria()); + esq.setExpectedWordCount(question.getDefaultExpectedWordCount()); + esq.setEvaluationType(question.getDefaultEvaluationType()); + return processPreview(esq); + }) + .orElse(notFound()); + } + + @Authenticated + @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) + public Result getExamSectionQuestionPreview(Long esqId, Http.Request request) { + User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + ExpressionList el = DB + .find(ExamSectionQuestion.class) + .fetch("question", "id, type, question") + .fetch("question.attachment", "fileName") + .fetch("options") + .fetch("options.option", "id, option") + .where() + .idEq(esqId); + if (user.hasRole(Role.Name.TEACHER)) { + el = el.or().in("question.questionOwners", user).in("examSection.exam.examOwners", user).endOr(); + } + return el.findOneOrEmpty().map(this::processPreview).orElse(notFound()); + } } diff --git a/app/controllers/QuestionReviewController.java b/app/controllers/QuestionReviewController.java index 866212038f..2d915dcf9b 100644 --- a/app/controllers/QuestionReviewController.java +++ b/app/controllers/QuestionReviewController.java @@ -18,7 +18,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import java.util.Arrays; import java.util.Collections; @@ -60,7 +60,7 @@ private boolean canAssess(User user, Exam exam) { @Restrict({ @Group("TEACHER") }) @Anonymous(filteredProperties = { "user", "creator", "modifier" }) public Result getEssays(Long examId, Optional> ids, Http.Request request) { - Exam exam = Ebean.find(Exam.class, examId); + Exam exam = DB.find(Exam.class, examId); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (exam == null || !exam.isInspectedOrCreatedOrOwnedBy(user)) { return badRequest(); @@ -75,22 +75,10 @@ public Result getEssays(Long examId, Optional> ids, Http.Request requ .map(ExamSectionQuestion::getQuestion) .filter(question -> question.getType() == Question.Type.EssayQuestion) .filter(question -> questionIds.isEmpty() || questionIds.contains(question.getId())) - .collect(Collectors.toList()); + .toList(); - // Comparator for ordering questions, have to take to account that answer's question is no longer found - Comparator comparator = (o1, o2) -> { - List l = questionSequence.stream().map(GeneratedIdentityModel::getId).collect(Collectors.toList()); - if (!l.contains(o1.getId())) { - return 1; - } - if (!l.contains(o2.getId())) { - return -1; - } - return l.indexOf(o1.getId()) - l.indexOf(o2.getId()); - }; - - // Ordered map of questions to answers - Map> questionMap = new TreeMap<>(comparator); + // Ordered map for questions, have to take to account that answer's question is no longer found + Map> questionMap = createMapping(questionSequence); // All the answers for questions in this exam List answers = exam @@ -102,9 +90,9 @@ public Result getEssays(Long examId, Optional> ids, Http.Request requ .flatMap(es -> es.getSectionQuestions().stream()) .filter(esq -> esq.getQuestion().getType() == Question.Type.EssayQuestion) .filter(esq -> questionIds.isEmpty() || questionIds.contains(esq.getQuestion().getParent().getId())) - .collect(Collectors.toList()); + .toList(); - // Get evaluation criterias from parent exam section questions + // Get evaluation criteria from parent exam section questions Map evaluationCriteriaMap = exam .getExamSections() .stream() @@ -137,12 +125,28 @@ public Result getEssays(Long examId, Optional> ids, Http.Request requ String evaluationCriteria = evaluationCriteriaMap.get(key); return new QuestionEntry(e.getKey(), e.getValue(), evaluationCriteria).toJson(); }) - .collect(Collectors.toList()); + .toList(); String json = String.format("[%s]", String.join(", ", results)); return writeAnonymousResult(request, ok(json).as("application/json"), exam.isAnonymous()); } + private static Map> createMapping(List questions) { + Comparator comparator = (o1, o2) -> { + List ids = questions.stream().map(GeneratedIdentityModel::getId).toList(); + if (!ids.contains(o1.getId())) { + return 1; + } + if (!ids.contains(o2.getId())) { + return -1; + } + return ids.indexOf(o1.getId()) - ids.indexOf(o2.getId()); + }; + + // Ordered map of questions to answers + return new TreeMap<>(comparator); + } + // DTO private static class QuestionEntry { @@ -156,9 +160,9 @@ private static class QuestionEntry { "examSection(name, exam(id, hash, creator(id, email, userIdentifier, firstName, lastName), " + "state, examInspections(user(id)))))" ); - this.question = Ebean.json().toJson(question, PathProperties.parse("(attachment(*), *)")); - this.answers = answers.stream().map(a -> Ebean.json().toJson(a, pp)).collect(Collectors.toList()); - this.evaluationCriteria = Ebean.json().toJson(evaluationCriteria); + this.question = DB.json().toJson(question, PathProperties.parse("(attachment(*), *)")); + this.answers = answers.stream().map(a -> DB.json().toJson(a, pp)).toList(); + this.evaluationCriteria = DB.json().toJson(evaluationCriteria); } private String toJson() { diff --git a/app/controllers/ReportController.java b/app/controllers/ReportController.java index d7446599ab..419639de39 100644 --- a/app/controllers/ReportController.java +++ b/app/controllers/ReportController.java @@ -17,11 +17,13 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; +import io.ebean.text.PathProperties; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -62,7 +64,7 @@ public ReportController(ExcelBuilder excelBuilder) { @Restrict({ @Group("ADMIN") }) public Result listDepartments() { - List courses = Ebean.find(Course.class).where().isNotNull("department").findList(); + List courses = DB.find(Course.class).where().isNotNull("department").findList(); Set departments = courses.stream().map(Course::getDepartment).collect(Collectors.toSet()); ObjectNode node = Json.newObject(); ArrayNode arrayNode = node.putArray("departments"); @@ -96,11 +98,13 @@ private ExpressionList applyFilters( @Restrict({ @Group("ADMIN") }) public Result getExamParticipations(Optional dept, Optional start, Optional end) { - List enrolments = Ebean - .find(ExamEnrolment.class) - .fetch("exam", "id, created") - .fetch("externalExam", "id, started") - .where() + PathProperties pp = PathProperties.parse( + "noShow, exam(created, course(department)), " + + "externalExam(started), reservation(machine(room(id, name, outOfService)))" + ); + ExpressionList el = DB.find(ExamEnrolment.class).where(); + el.apply(pp); + List enrolments = el .or() .ne("exam.state", Exam.State.PUBLISHED) .isNotNull("externalExam.started") @@ -110,18 +114,21 @@ public Result getExamParticipations(Optional dept, Optional star .findList() .stream() .filter(ee -> applyEnrolmentFilter(ee, dept, start, end)) - .collect(Collectors.toList()); - Map> roomMap = new HashMap<>(); + .toList(); + Map> roomMap = new HashMap<>(); for (ExamEnrolment enrolment : enrolments) { ExamRoom room = enrolment.getReservation().getMachine().getRoom(); String key = String.format("%d___%s", room.getId(), room.getName()); if (!roomMap.containsKey(key)) { roomMap.put(key, new ArrayList<>()); } - roomMap.get(key).add(enrolment); + DateTime examStart = enrolment.getExternalExam() != null + ? enrolment.getExternalExam().getStarted() + : enrolment.getExam().getCreated(); + roomMap.get(key).add(new Participation(examStart)); } // Fill in the rooms that have no associated participations - List rooms = Ebean.find(ExamRoom.class).where().eq("outOfService", false).findList(); + List rooms = DB.find(ExamRoom.class).where().eq("outOfService", false).findList(); for (ExamRoom room : rooms) { String key = String.format("%d___%s", room.getId(), room.getName()); if (!roomMap.containsKey(key)) { @@ -129,11 +136,24 @@ public Result getExamParticipations(Optional dept, Optional star roomMap.put(key, new ArrayList<>()); } } - return ok(roomMap); + return ok(Json.toJson(roomMap)); } // DTO for minimizing output from this API - private class ExamInfo { + private static class Participation { + + String date; + + Participation(DateTime date) { + this.date = ISODateTimeFormat.dateTime().print(date); + } + + public String getDate() { + return date; + } + } + + private static class ExamInfo { String name; Integer participations; @@ -153,7 +173,7 @@ public String getState() { } private boolean applyExamFilter(Exam e, Optional start, Optional end) { - Boolean result = e.getState().ordinal() > Exam.State.PUBLISHED.ordinal() && e.getExamParticipation() != null; + boolean result = e.getState().ordinal() > Exam.State.PUBLISHED.ordinal() && e.getExamParticipation() != null; DateTime created = e.getCreated(); if (start.isPresent()) { DateTime startDate = DateTime.parse(start.get(), ISODateTimeFormat.dateTimeParser()); @@ -173,7 +193,7 @@ private boolean applyEnrolmentFilter( Optional end ) { DateTime created = ee.getExam() != null ? ee.getExam().getCreated() : ee.getExternalExam().getStarted(); - Boolean result = true; + boolean result = true; if (dept.isPresent()) { if (ee.getExternalExam() != null) { return false; @@ -195,7 +215,7 @@ private boolean applyEnrolmentFilter( @Restrict({ @Group("ADMIN") }) public Result getPublishedExams(Optional dept, Optional start, Optional end) { - ExpressionList query = Ebean + ExpressionList query = DB .find(Exam.class) .fetch("course", "code") .where() @@ -220,7 +240,7 @@ public Result getPublishedExams(Optional dept, Optional start, O @Restrict({ @Group("ADMIN") }) public Result getReservations(Optional dept, Optional start, Optional end) { - ExpressionList query = Ebean.find(Reservation.class).where(); + ExpressionList query = DB.find(ExamEnrolment.class).where(); query = applyFilters( query, @@ -230,24 +250,47 @@ public Result getReservations(Optional dept, Optional start, Opt start.orElse(null), end.orElse(null) ); - return ok(query.findList()); + Set enrolments = query.findSet(); + long noShows = enrolments.stream().filter(ExamEnrolment::isNoShow).count(); + long appearances = enrolments.size() - noShows; + return ok(Json.newObject().put("noShows", noShows).put("appearances", appearances)); } @Restrict({ @Group("ADMIN") }) public Result getResponses(Optional dept, Optional start, Optional end) { - ExpressionList query = Ebean.find(Exam.class).where().isNotNull("parent").isNotNull("course"); + ExpressionList query = DB.find(Exam.class).where().isNotNull("parent").isNotNull("course"); query = applyFilters(query, "course", "created", dept.orElse(null), start.orElse(null), end.orElse(null)); Set exams = query.findSet(); - List infos = new ArrayList<>(); - for (Exam exam : exams + long aborted = exams.stream().filter(e -> e.getState() == Exam.State.ABORTED).count(); + long assessed = exams .stream() - .filter(e -> e.getState().ordinal() > Exam.State.PUBLISHED.ordinal()) - .collect(Collectors.toList())) { - ExamInfo info = new ExamInfo(); - info.state = exam.getState().toString(); - infos.add(info); - } - return ok(Json.toJson(infos)); + .filter(e -> + e.hasState( + Exam.State.GRADED, + Exam.State.GRADED_LOGGED, + Exam.State.ARCHIVED, + Exam.State.REJECTED, + Exam.State.DELETED + ) + ) + .count(); + long unAssessed = exams + .stream() + .filter(e -> + e.hasState( + Exam.State.INITIALIZED, + Exam.State.STUDENT_STARTED, + Exam.State.REVIEW, + Exam.State.REVIEW_STARTED + ) + ) + .count(); + JsonNode node = Json + .newObject() + .put("aborted", aborted) + .put("assessed", assessed) + .put("unAssessed", unAssessed); + return ok(node); } @With(ExamRecordSanitizer.class) @@ -257,8 +300,8 @@ public Result exportExamQuestionScoresAsExcel(Long examId, Http.Request request) ByteArrayOutputStream bos; try { bos = excelBuilder.buildScoreExcel(examId, childIds); - } catch (IOException e) { - return internalServerError("sitnet_error_creating_csv_file"); + } catch (IOException | RuntimeException e) { + return internalServerError("i18n_error_creating_csv_file"); } return ok(Base64.getEncoder().encodeToString(bos.toByteArray())) .withHeader("Content-Disposition", "attachment; filename=\"exam_records.xlsx\"") diff --git a/app/controllers/ReservationController.java b/app/controllers/ReservationController.java index 73de7ddc7e..ee5ef3e9cc 100644 --- a/app/controllers/ReservationController.java +++ b/app/controllers/ReservationController.java @@ -19,22 +19,17 @@ import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; import controllers.iop.collaboration.api.CollaborativeExamLoader; import controllers.iop.transfer.api.ExternalReservationHandler; import exceptions.NotFoundException; import impl.EmailComposer; -import io.ebean.Ebean; -import io.ebean.ExpressionList; +import io.ebean.DB; import io.ebean.FetchConfig; -import io.ebean.Query; import io.ebean.text.PathProperties; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; @@ -57,6 +52,7 @@ import sanitizers.Attrs; import security.Authenticated; import system.interceptors.Anonymous; +import util.datetime.DateTimeHandler; public class ReservationController extends BaseController { @@ -69,14 +65,17 @@ public class ReservationController extends BaseController { @Inject protected ExternalReservationHandler externalReservationHandler; + @Inject + protected DateTimeHandler dateTimeHandler; + @Authenticated @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result getExams(Http.Request request, Optional filter) { - User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - PathProperties props = PathProperties.parse("(id, name)"); - Query q = Ebean.createQuery(Exam.class); + var user = request.attrs().get(Attrs.AUTHENTICATED_USER); + var props = PathProperties.parse("(id, name)"); + var q = DB.createQuery(Exam.class); props.apply(q); - ExpressionList el = q + var el = q .where() .isNull("parent") // only Exam prototypes .eq("state", Exam.State.PUBLISHED); @@ -86,7 +85,7 @@ public Result getExams(Http.Request request, Optional filter) { if (user.hasRole(Role.Name.TEACHER)) { el = el - .gt("examActiveEndDate", new Date()) + .gt("periodEnd", new Date()) .disjunction() .eq("creator", user) .eq("examOwners", user) @@ -94,24 +93,23 @@ public Result getExams(Http.Request request, Optional filter) { .eq("shared", true) .endJunction(); } - List exams = el.findList(); - return ok(exams, props); + return ok(el.findList(), props); } @Restrict({ @Group("ADMIN") }) public Result getExamRooms() { - List examRooms = Ebean.find(ExamRoom.class).select("id, name").fetch("examMachines", "id").findList(); + var examRooms = DB.find(ExamRoom.class).select("id, name").fetch("examMachines", "id").findList(); return ok(examRooms); } private ArrayNode asJson(List users) { - ArrayNode array = JsonNodeFactory.instance.arrayNode(); - for (User u : users) { - String name = String.format("%s %s", u.getFirstName(), u.getLastName()); + var array = JsonNodeFactory.instance.arrayNode(); + for (var u : users) { + var name = String.format("%s %s", u.getFirstName(), u.getLastName()); if (u.getUserIdentifier() != null) { name += String.format(" (%s)", u.getUserIdentifier()); } - ObjectNode part = Json.newObject(); + var part = Json.newObject(); part.put("id", u.getId()); part.put("firstName", u.getFirstName()); part.put("lastName", u.getLastName()); @@ -124,55 +122,42 @@ private ArrayNode asJson(List users) { @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result getStudents(Optional filter) { - ExpressionList el = Ebean.find(User.class).where().eq("roles.name", "STUDENT"); + var el = DB.find(User.class).where().eq("roles.name", "STUDENT"); if (filter.isPresent()) { el = el.or().ilike("userIdentifier", String.format("%%%s%%", filter.get())); el = applyUserFilter(null, el, filter.get()).endOr(); } - List students = el.findList(); - return ok(Json.toJson(asJson(students))); + return ok(Json.toJson(asJson(el.findList()))); } @Restrict({ @Group("ADMIN") }) public Result getTeachers(Optional filter) { - ExpressionList el = Ebean.find(User.class).where().eq("roles.name", "TEACHER"); + var el = DB.find(User.class).where().eq("roles.name", "TEACHER"); if (filter.isPresent()) { el = applyUserFilter(null, el.or(), filter.get()).endOr(); } - List teachers = el.findList(); - return ok(Json.toJson(asJson(teachers))); + return ok(Json.toJson(asJson(el.findList()))); } @Restrict({ @Group("ADMIN") }) public CompletionStage removeReservation(long id, Http.Request request) throws NotFoundException { - DynamicForm df = formFactory.form().bindFromRequest(request); - String msg = df.get("msg"); - - ExamEnrolment enrolment = Ebean.find(ExamEnrolment.class).where().eq("reservation.id", id).findOne(); - + var enrolment = DB.find(ExamEnrolment.class).where().eq("reservation.id", id).findOne(); if (enrolment == null) { throw new NotFoundException(String.format("No reservation with id %d for current user.", id)); } - - ExamParticipation participation = Ebean - .find(ExamParticipation.class) - .where() - .eq("exam", enrolment.getExam()) - .findOne(); - + var participation = DB.find(ExamParticipation.class).where().eq("exam", enrolment.getExam()).findOne(); if (participation != null) { return wrapAsPromise( - forbidden(String.format("sitnet_unable_to_remove_reservation (id=%d).", participation.getId())) + forbidden(String.format("i18n_unable_to_remove_reservation (id=%d).", participation.getId())) ); } - - Reservation reservation = enrolment.getReservation(); + var reservation = enrolment.getReservation(); + var msg = formFactory.form().bindFromRequest(request).get("msg"); // Let's not send emails about historical reservations if (reservation.getEndAt().isAfter(DateTime.now())) { - User student = enrolment.getUser(); + var student = enrolment.getUser(); emailComposer.composeReservationCancellationNotification(student, reservation, msg, false, enrolment); } - if (reservation.getExternalReservation() != null) { return externalReservationHandler.removeReservation(reservation, enrolment.getUser(), msg); } else { @@ -185,26 +170,26 @@ public CompletionStage removeReservation(long id, Http.Request request) @Restrict({ @Group("ADMIN") }) public Result findAvailableMachines(Long reservationId) throws ExecutionException, InterruptedException { - Reservation reservation = Ebean.find(Reservation.class, reservationId); + var reservation = DB.find(Reservation.class, reservationId); if (reservation == null) { return notFound(); } - PathProperties props = PathProperties.parse("(id, name)"); - Query query = Ebean.createQuery(ExamMachine.class); + var props = PathProperties.parse("(id, name)"); + var query = DB.createQuery(ExamMachine.class); props.apply(query); - List candidates = query + var candidates = query .where() .eq("room", reservation.getMachine().getRoom()) .ne("outOfService", true) .ne("archived", true) .findList(); - final Exam exam = getReservationExam(reservation); - Iterator it = candidates.listIterator(); + var exam = getReservationExam(reservation); + var it = candidates.listIterator(); while (it.hasNext()) { - ExamMachine machine = it.next(); - if (!machine.hasRequiredSoftware(exam)) { + var machine = it.next(); + if (exam.isPresent() && !machine.hasRequiredSoftware(exam.get())) { it.remove(); } if (machine.isReservedDuring(reservation.toInterval())) { @@ -217,26 +202,29 @@ public Result findAvailableMachines(Long reservationId) throws ExecutionExceptio @Restrict({ @Group("ADMIN") }) public Result updateMachine(Long reservationId, Http.Request request) throws ExecutionException, InterruptedException { - Reservation reservation = Ebean.find(Reservation.class, reservationId); + var reservation = DB.find(Reservation.class, reservationId); if (reservation == null) { return notFound(); } - DynamicForm df = formFactory.form().bindFromRequest(request); - Long machineId = Long.parseLong(df.get("machineId")); - PathProperties props = PathProperties.parse("(id, name, room(id, name))"); - Query query = Ebean.createQuery(ExamMachine.class); + var machineId = request.body().asJson().get("machineId").asLong(); + var props = PathProperties.parse("(id, name, room(id, name))"); + var query = DB.createQuery(ExamMachine.class); props.apply(query); - ExamMachine previous = reservation.getMachine(); - ExamMachine machine = query.where().idEq(machineId).findOne(); + var previous = reservation.getMachine(); + var machine = query.where().idEq(machineId).findOne(); if (machine == null) { return notFound(); } if (!machine.getRoom().equals(reservation.getMachine().getRoom())) { return forbidden("Not allowed to change to use a machine from a different room"); } - Exam exam = getReservationExam(reservation); - if (!machine.hasRequiredSoftware(exam) || machine.isReservedDuring(reservation.toInterval())) { + var exam = getReservationExam(reservation); + if ( + exam.isEmpty() || + !machine.hasRequiredSoftware(exam.get()) || + machine.isReservedDuring(reservation.toInterval()) + ) { return forbidden("Machine not eligible for choosing"); } reservation.setMachine(machine); @@ -250,14 +238,13 @@ public Result updateMachine(Long reservationId, Http.Request request) return ok(machine, props); } - private Exam getReservationExam(Reservation reservation) throws InterruptedException, ExecutionException { + private Optional getReservationExam(Reservation reservation) throws InterruptedException, ExecutionException { return reservation.getEnrolment().getExam() != null - ? reservation.getEnrolment().getExam() + ? Optional.of(reservation.getEnrolment().getExam()) : collaborativeExamLoader .downloadExam(reservation.getEnrolment().getCollaborativeExam()) .toCompletableFuture() - .get() - .orElse(null); + .get(); } @Authenticated @@ -272,19 +259,19 @@ public Result getExaminationEvents( Optional end, Http.Request request ) { - ExpressionList query = Ebean + var query = DB .find(ExamEnrolment.class) .fetch("user", "id, firstName, lastName, email, userIdentifier") .fetch("exam", "id, name, state, trialCount, implementation") .fetch("exam.course", "code") - .fetch("exam.examOwners", "id, firstName, lastName", new FetchConfig().query()) - .fetch("exam.parent.examOwners", "id, firstName, lastName", new FetchConfig().query()) + .fetch("exam.examOwners", "id, firstName, lastName", FetchConfig.ofQuery()) + .fetch("exam.parent.examOwners", "id, firstName, lastName", FetchConfig.ofQuery()) .fetch("exam.examInspections.user", "id, firstName, lastName") .fetch("examinationEventConfiguration.examinationEvent") .where() .isNotNull("examinationEventConfiguration") .isNotNull("exam"); - User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + var user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (user.hasRole(Role.Name.TEACHER)) { query = query @@ -296,23 +283,17 @@ public Result getExaminationEvents( } if (start.isPresent()) { - DateTime startDate = DateTime.parse(start.get(), ISODateTimeFormat.dateTimeParser()); + var startDate = DateTime.parse(start.get(), ISODateTimeFormat.dateTimeParser()); query = query.ge("examinationEventConfiguration.examinationEvent.start", startDate.toDate()); } if (state.isPresent()) { - switch (state.get()) { - case "NO_SHOW": - query = query.eq("noShow", true); - break; - case "EXTERNAL_UNFINISHED": - case "EXTERNAL_FINISHED": - query = query.isNull("id"); // Deliberately force an empty result set - break; - default: - query = query.eq("exam.state", Exam.State.valueOf(state.get())).eq("noShow", false); - break; - } + query = + switch (state.get()) { + case "NO_SHOW" -> query.eq("noShow", true); + case "EXTERNAL_UNFINISHED", "EXTERNAL_FINISHED" -> query.isNull("id"); // Deliberately force an empty result set + default -> query.eq("exam.state", Exam.State.valueOf(state.get())).eq("noShow", false); + }; } if (studentId.isPresent()) { @@ -333,7 +314,7 @@ public Result getExaminationEvents( } if (ownerId.isPresent() && user.hasRole(Role.Name.ADMIN)) { - Long userId = ownerId.get(); + var userId = ownerId.get(); query = query .disjunction() @@ -341,7 +322,7 @@ public Result getExaminationEvents( .eq("exam.parent.examOwners.id", userId) .endJunction(); } - List enrolments = query + var enrolments = query .orderBy("examinationEventConfiguration.examinationEvent.start") .findList() .stream() @@ -349,19 +330,18 @@ public Result getExaminationEvents( if (end.isEmpty()) { return true; } - DateTime endDate = DateTime.parse(end.get(), ISODateTimeFormat.dateTimeParser()); - DateTime eventEnd = ee + var endDate = DateTime.parse(end.get(), ISODateTimeFormat.dateTimeParser()); + var eventEnd = ee .getExaminationEventConfiguration() .getExaminationEvent() .getStart() .plusMinutes(ee.getExam().getDuration()); return eventEnd.isBefore(endDate); }) - .collect(Collectors.toList()); - - final Result result = ok(enrolments); + .toList(); - final Set anonIds = enrolments + var result = ok(enrolments); + var anonIds = enrolments .stream() .filter(ee -> ee.getExam().isAnonymous()) .map(GeneratedIdentityModel::getId) @@ -384,15 +364,15 @@ public Result getReservations( Optional externalRef, Http.Request request ) { - ExpressionList query = Ebean + var query = DB .find(Reservation.class) .fetch("enrolment", "noShow, retrialPermitted") .fetch("user", "id, firstName, lastName, email, userIdentifier") .fetch("enrolment.exam", "id, name, state, trialCount, implementation") .fetch("enrolment.externalExam", "id, externalRef, finished") .fetch("enrolment.exam.course", "code") - .fetch("enrolment.exam.examOwners", "id, firstName, lastName", new FetchConfig().query()) - .fetch("enrolment.exam.parent.examOwners", "id, firstName, lastName", new FetchConfig().query()) + .fetch("enrolment.exam.examOwners", "id, firstName, lastName", FetchConfig.ofQuery()) + .fetch("enrolment.exam.parent.examOwners", "id, firstName, lastName", FetchConfig.ofQuery()) .fetch("enrolment.exam.examInspections.user", "id, firstName, lastName") .fetch("enrolment.exam.executionType", "type") .fetch("enrolment.collaborativeExam", "*") @@ -401,7 +381,7 @@ public Result getReservations( .fetch("machine.room", "id, name, roomCode") .where(); - User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + var user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (user.hasRole(Role.Name.TEACHER)) { query = query @@ -415,31 +395,31 @@ public Result getReservations( } if (start.isPresent()) { - DateTime startDate = DateTime.parse(start.get(), ISODateTimeFormat.dateTimeParser()); - query = query.ge("startAt", startDate.toDate()); + var startDate = DateTime.parse(start.get(), ISODateTimeFormat.dateTimeParser()); + var offset = dateTimeHandler.getTimezoneOffset(startDate.withDayOfYear(1)); + query = query.ge("startAt", startDate.plusMillis(offset)); } if (end.isPresent()) { - DateTime endDate = DateTime.parse(end.get(), ISODateTimeFormat.dateTimeParser()); - query = query.lt("endAt", endDate.toDate()); + var endDate = DateTime.parse(end.get(), ISODateTimeFormat.dateTimeParser()); + var offset = dateTimeHandler.getTimezoneOffset(endDate.withDayOfYear(1)); + query = query.lt("endAt", endDate.plusMillis(offset)); } if (state.isPresent()) { - switch (state.get()) { - case "NO_SHOW": - query = query.eq("enrolment.noShow", true); - break; - case "EXTERNAL_UNFINISHED": - query = query.isNotNull("externalUserRef").isNull("enrolment.externalExam.finished"); - break; - case "EXTERNAL_FINISHED": - query = query.isNotNull("externalUserRef").isNotNull("enrolment.externalExam.finished"); - break; - default: - query = - query.eq("enrolment.exam.state", Exam.State.valueOf(state.get())).eq("enrolment.noShow", false); - break; - } + query = + switch (state.get()) { + case "NO_SHOW" -> query.eq("enrolment.noShow", true); + case "EXTERNAL_UNFINISHED" -> query + .isNotNull("externalUserRef") + .isNull("enrolment.externalExam.finished"); + case "EXTERNAL_FINISHED" -> query + .isNotNull("externalUserRef") + .isNotNull("enrolment.externalExam.finished"); + default -> query + .eq("enrolment.exam.state", Exam.State.valueOf(state.get())) + .eq("enrolment.noShow", false); + }; } if (studentId.isPresent()) { @@ -471,7 +451,7 @@ public Result getReservations( } if (ownerId.isPresent() && user.hasRole(Role.Name.ADMIN)) { - Long userId = ownerId.get(); + var userId = ownerId.get(); query = query .disjunction() @@ -479,11 +459,9 @@ public Result getReservations( .eq("enrolment.exam.parent.examOwners.id", userId) .endJunction(); } - Set reservations = query.orderBy("startAt").findSet(); - - final Result result = ok(reservations); - - final Set anonIds = reservations + var reservations = query.orderBy("startAt").findSet(); + var result = ok(reservations); + var anonIds = reservations .stream() .filter(r -> r.getEnrolment() != null && diff --git a/app/controllers/ReviewController.java b/app/controllers/ReviewController.java index cc65e23774..974bd6125e 100644 --- a/app/controllers/ReviewController.java +++ b/app/controllers/ReviewController.java @@ -15,40 +15,24 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import controllers.base.BaseController; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.FetchConfig; import io.ebean.Query; import io.ebean.text.PathProperties; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Base64; import java.util.Collection; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import java.util.zip.GZIPOutputStream; import javax.inject.Inject; -import models.Attachment; import models.Comment; import models.Exam; import models.ExamEnrolment; @@ -67,21 +51,14 @@ import models.questions.ClozeTestAnswer; import models.questions.EssayAnswer; import models.questions.Question; -import models.sections.ExamSection; import models.sections.ExamSectionQuestion; -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; -import org.apache.commons.compress.utils.IOUtils; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.jsoup.Jsoup; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.data.DynamicForm; import play.i18n.Lang; import play.i18n.MessagesApi; -import play.libs.Files.TemporaryFile; import play.libs.Json; import play.mvc.Http; import play.mvc.Result; @@ -92,7 +69,6 @@ import scala.concurrent.duration.Duration; import security.Authenticated; import system.interceptors.Anonymous; -import util.csv.CsvBuilder; import util.file.FileHandler; public class ReviewController extends BaseController { @@ -102,9 +78,6 @@ public class ReviewController extends BaseController { @Inject protected EmailComposer emailComposer; - @Inject - protected CsvBuilder csvBuilder; - @Inject protected FileHandler fileHandler; @@ -114,18 +87,18 @@ public class ReviewController extends BaseController { @Inject protected MessagesApi messaging; - private static final Logger.ALogger logger = Logger.of(ReviewController.class); + private final Logger logger = LoggerFactory.getLogger(ReviewController.class); @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Anonymous(filteredProperties = { "user", "preEnrolledUserEmail", "grade" }) public Result getParticipationsForExamAndUser(Long eid, Http.Request request) { - final Exam exam = Ebean.find(Exam.class, eid); + final Exam exam = DB.find(Exam.class, eid); if (exam == null) { return notFound(); } - List participations = Ebean + List participations = DB .find(ExamParticipation.class) .fetch("exam", "id, state, anonymous") .fetch("exam.grade", "id, name") @@ -146,11 +119,11 @@ public Result getParticipationsForExamAndUser(Long eid, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Anonymous(filteredProperties = { "user", "preEnrolledUserEmail" }) public Result listNoShowsForExamAndUser(Long eid, Http.Request request) { - final Exam exam = Ebean.find(Exam.class, eid); + final Exam exam = DB.find(Exam.class, eid); if (exam == null) { return notFound(); } - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .fetch("reservation", "startAt, endAt") .fetch("examinationEventConfiguration.examinationEvent", "start") @@ -185,11 +158,11 @@ public Result getExamReview(Long eid, Http.Request request) { query = query.endJunction(); ExamParticipation examParticipation = query.findOne(); if (examParticipation == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = examParticipation.getExam(); if (!exam.isChildInspectedOrCreatedOrOwnedBy(user) && !isAdmin && !exam.isViewableForLanguageInspector(user)) { - return forbidden("sitnet_error_access_forbidden"); + return forbidden("i18n_error_access_forbidden"); } String blankAnswerText = messaging.get(Lang.forCode(user.getLanguage().getCode()), "clozeTest.blank.answer"); @@ -222,12 +195,12 @@ public Result getExamReviews(Long eid, Http.Request request) { "course(code, name, gradeScale(grades(*))), " + "examSections(name, sectionQuestions(*, clozeTestAnswer(*), question(*), essayAnswer(*), options(*, option(*)))), " + "languageInspection(*), examLanguages(*), examFeedback(*), grade(name), " + - "parent(name, examActiveStartDate, examActiveEndDate, course(code, name), examOwners(firstName, lastName, email)), " + + "parent(name, periodStart, periodEnd, course(code, name), examOwners(firstName, lastName, email), examInspections(id, user(firstName, lastName)))" + "examParticipation(*, user(id, firstName, lastName, email, userIdentifier)), " + - "examEnrolments(retrialPermitted)" + + "examEnrolments(retrialPermitted)," + ")" ); - Query query = Ebean.find(Exam.class); + Query query = DB.find(Exam.class); pp.apply(query); query .fetchQuery("course", "code, credits") @@ -278,7 +251,7 @@ public Result getExamReviews(Long eid, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result scoreExamQuestion(Long id, Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); - ExamSectionQuestion essayQuestion = Ebean.find(ExamSectionQuestion.class, id); + ExamSectionQuestion essayQuestion = DB.find(ExamSectionQuestion.class, id); if (essayQuestion == null) { return notFound("question not found"); } @@ -301,7 +274,7 @@ public Result scoreExamQuestion(Long id, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result forceScoreExamQuestion(Long id, Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); - Optional oeq = Ebean + Optional oeq = DB .find(ExamSectionQuestion.class) .fetch("examSection.exam.parent.examOwners") .where() @@ -335,7 +308,7 @@ public Result forceScoreExamQuestion(Long id, Http.Request request) { @Restrict({ @Group("TEACHER") }) public Result updateAssessmentInfo(Long id, Http.Request request) { String info = request.body().asJson().get("assessmentInfo").asText(); - Optional option = Ebean + Optional option = DB .find(Exam.class) .fetch("parent.creator") .where() @@ -343,7 +316,7 @@ public Result updateAssessmentInfo(Long id, Http.Request request) { .in("state", Exam.State.GRADED_LOGGED, Exam.State.ARCHIVED) .findOneOrEmpty(); if (option.isEmpty()) { - return notFound("sitnet_exam_not_found"); + return notFound("i18n_exam_not_found"); } Exam exam = option.get(); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); @@ -362,9 +335,9 @@ public Result updateAssessmentInfo(Long id, Http.Request request) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result reviewExam(Long id, Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); - Exam exam = Ebean.find(Exam.class).fetch("parent").fetch("parent.creator").where().idEq(id).findOne(); + Exam exam = DB.find(Exam.class).fetch("parent").fetch("parent.creator").where().idEq(id).findOne(); if (exam == null) { - return notFound("sitnet_exam_not_found"); + return notFound("i18n_exam_not_found"); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); Exam.State newState = Exam.State.valueOf(df.get("state")); @@ -382,7 +355,7 @@ public Result reviewExam(Long id, Http.Request request) { Integer grade = df.get("grade") == null ? null : Integer.parseInt(df.get("grade")); String additionalInfo = df.get("additionalInfo"); if (grade != null) { - Grade examGrade = Ebean.find(Grade.class, grade); + Grade examGrade = DB.find(Grade.class, grade); GradeScale scale = exam.getGradeScale() == null ? exam.getCourse().getGradeScale() : exam.getGradeScale(); if (scale.getGrades().contains(examGrade)) { exam.setGrade(examGrade); @@ -401,7 +374,7 @@ public Result reviewExam(Long id, Http.Request request) { creditType = df.get("creditType"); } if (creditType != null) { - ExamType eType = Ebean.find(ExamType.class).where().eq("type", creditType).findOne(); + ExamType eType = DB.find(ExamType.class).where().eq("type", creditType).findOne(); if (eType != null) { exam.setCreditType(eType); } @@ -422,9 +395,9 @@ public Result reviewExam(Long id, Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result sendInspectionMessage(Long eid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } JsonNode body = request.body().asJson(); if (!body.has("msg")) { @@ -432,7 +405,7 @@ public Result sendInspectionMessage(Long eid, Http.Request request) { } User loggedUser = request.attrs().get(Attrs.AUTHENTICATED_USER); - List inspections = Ebean + List inspections = DB .find(ExamInspection.class) .fetch("user") .fetch("exam") @@ -464,10 +437,11 @@ public Result sendInspectionMessage(Long eid, Http.Request request) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) @Anonymous(filteredProperties = { "user" }) - public Result listNoShows(Long eid, Http.Request request) { - List enrolments = Ebean + public Result listNoShows(Long eid, Optional collaborative, Http.Request request) { + ExpressionList el = DB .find(ExamEnrolment.class) .fetch("exam", "id, name, state, gradedTime, customCredit, trialCount, anonymous") + .fetch("collaborativeExam") .fetch("exam.executionType") .fetch("reservation") .fetch("examinationEventConfiguration.examinationEvent") @@ -475,17 +449,15 @@ public Result listNoShows(Long eid, Http.Request request) { .fetch("exam.course", "code, credits") .fetch("exam.grade", "id, name") .where() - .or() - .eq("exam.id", eid) - .eq("exam.parent.id", eid) - .endOr() - .eq("noShow", true) - .orderBy("reservation.endAt") - .findList(); + .eq("noShow", true); + var query = collaborative.orElse(false) + ? el.eq("collaborativeExam.id", eid) + : el.or().eq("exam.id", eid).eq("exam.parent.id", eid).endOr(); + var enrolments = query.findList(); final Result result = ok(enrolments); Set anonIds = enrolments .stream() - .filter(e -> e.getExam().isAnonymous()) + .filter(e -> e.getCollaborativeExam() != null || e.getExam().isAnonymous()) .map(GeneratedIdentityModel::getId) .collect(Collectors.toSet()); return writeAnonymousResult(request, result, anonIds); @@ -495,9 +467,9 @@ public Result listNoShows(Long eid, Http.Request request) { @With(CommentSanitizer.class) @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result updateComment(Long eid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } if (exam.hasState(Exam.State.ABORTED, Exam.State.GRADED_LOGGED, Exam.State.ARCHIVED)) { return forbidden(); @@ -506,7 +478,7 @@ public Result updateComment(Long eid, Http.Request request) { Optional commentId = request.attrs().getOptional(Attrs.COMMENT_ID); Comment comment = commentId.isEmpty() ? new Comment() - : Ebean.find(Comment.class).fetch("creator", "firstName, lastName").where().idEq(commentId.get()).findOne(); + : DB.find(Comment.class).fetch("creator", "firstName, lastName").where().idEq(commentId.get()).findOne(); if (comment == null) { return notFound(); } @@ -531,14 +503,14 @@ public Result updateComment(Long eid, Http.Request request) { @With(CommentSanitizer.class) @Restrict({ @Group("STUDENT") }) public Result setCommentStatusRead(Long eid, Long cid, Http.Request request) { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } if (exam.hasState(Exam.State.ABORTED, Exam.State.ARCHIVED)) { return forbidden(); } - Comment comment = Ebean.find(Comment.class, cid); + Comment comment = DB.find(Comment.class, cid); if (comment == null) { return notFound(); } @@ -555,7 +527,7 @@ public Result setCommentStatusRead(Long eid, Long cid, Http.Request request) { @With(CommentSanitizer.class) @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result addInspectionComment(Long id, Http.Request request) { - Exam exam = Ebean.find(Exam.class, id); + Exam exam = DB.find(Exam.class, id); if (exam == null) { return notFound("Inspection not found"); } @@ -573,7 +545,7 @@ public Result addInspectionComment(Long id, Http.Request request) { @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result archiveExams(Http.Request request) { Collection ids = request.attrs().get(Attrs.ID_COLLECTION); - List exams = Ebean.find(Exam.class).where().eq("state", Exam.State.GRADED_LOGGED).idIn(ids).findList(); + List exams = DB.find(Exam.class).where().eq("state", Exam.State.GRADED_LOGGED).idIn(ids).findList(); for (Exam e : exams) { e.setState(Exam.State.ARCHIVED); e.update(); @@ -586,7 +558,7 @@ public Result hasLockedAssessments(Long eid) { // if no assessments => everything // if assessments and type == locked => none // else date only - Set assessments = Ebean + Set assessments = DB .find(Exam.class) .where() .eq("parent.id", eid) @@ -596,7 +568,7 @@ public Result hasLockedAssessments(Long eid) { if (assessments.isEmpty()) { return ok(Json.newObject().put("status", "everything")); } else { - Exam exam = Ebean.find(Exam.class, eid); + Exam exam = DB.find(Exam.class, eid); if ( exam != null && exam.getExamFeedbackConfig() != null && @@ -609,177 +581,6 @@ public Result hasLockedAssessments(Long eid) { } } - private static boolean isEligibleForArchiving(Exam exam, DateTime start, DateTime end) { - return ( - exam.hasState(Exam.State.ABORTED, Exam.State.REVIEW, Exam.State.REVIEW_STARTED) && - !(start != null && exam.getCreated().isBefore(start)) && - !(end != null && exam.getCreated().isAfter(end)) - ); - } - - private static void createSummaryFile( - ArchiveOutputStream aos, - DateTime start, - DateTime end, - Exam exam, - Map questions - ) throws IOException { - File file = File.createTempFile("summary", ".txt"); - FileOutputStream fos = new FileOutputStream(file); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos)); - - if (start != null || end != null) { - DateTimeFormatter dtf = DateTimeFormat.forPattern("dd.MM.yyyy"); - writer.write( - String.format("period: %s-%s", start == null ? "" : dtf.print(start), end == null ? "" : dtf.print(end)) - ); - writer.newLine(); - } - writer.write(String.format("exam id: %d", exam.getId())); - writer.newLine(); - writer.write(String.format("exam name: %s", exam.getName())); - writer.newLine(); - writer.newLine(); - writer.write("questions"); - writer.newLine(); - for (Map.Entry entry : questions.entrySet()) { - writer.write(String.format("%d: %s", entry.getKey(), Jsoup.parse(entry.getValue()).text())); - writer.newLine(); - } - writer.close(); - TarArchiveEntry entry = new TarArchiveEntry("summary.txt"); - entry.setSize(file.length()); - aos.putArchiveEntry(entry); - IOUtils.copy(new FileInputStream(file), aos); - aos.closeArchiveEntry(); - } - - private void createArchive(Exam prototype, ArchiveOutputStream aos, DateTime start, DateTime end) - throws IOException { - List children = prototype - .getChildren() - .stream() - .filter(e -> isEligibleForArchiving(e, start, end)) - .collect(Collectors.toList()); - Map questions = new LinkedHashMap<>(); - for (Exam exam : children) { - String uid = String.format( - "%s-%d", - exam.getCreator().getUserIdentifier() == null - ? exam.getCreator().getId().toString() - : exam.getCreator().getUserIdentifier(), - exam.getId() - ); - for (ExamSection es : exam.getExamSections()) { - List essays = es - .getSectionQuestions() - .stream() - .filter(esq -> esq.getQuestion().getType() == Question.Type.EssayQuestion) - .collect(Collectors.toList()); - for (ExamSectionQuestion esq : essays) { - Long questionId = esq.getQuestion().getParent() == null - ? esq.getQuestion().getId() - : esq.getQuestion().getParent().getId(); - questions.put(questionId, esq.getQuestion().getQuestion()); - String questionIdText = esq.getQuestion().getParent() == null - ? questionId + "#original_question_removed" - : Long.toString(esq.getQuestion().getParent().getId()); - EssayAnswer answer = esq.getEssayAnswer(); - Attachment attachment; - File file = null; - if (answer != null && (attachment = answer.getAttachment()) != null) { - // attached answer - String fileName = attachment.getFileName(); - file = new File(attachment.getFilePath()); - if (file.exists()) { - String entryName = String.format( - "%d/%s/%s/%s", - prototype.getId(), - questionIdText, - uid, - fileName - ); - TarArchiveEntry entry = new TarArchiveEntry(entryName); - entry.setSize(file.length()); - aos.putArchiveEntry(entry); - IOUtils.copy(new FileInputStream(file), aos); - } else { - logger.warn("Attachment {} is not connected to a file on disk!", attachment.getId()); - } - } - if (file == null || !file.exists()) { - // no attached answer, create empty directory - String entryName = String.format("%d/%d/%s/", prototype.getId(), questionId, uid); - TarArchiveEntry entry = new TarArchiveEntry(entryName); - aos.putArchiveEntry(entry); - } - aos.closeArchiveEntry(); - } - } - } - createSummaryFile(aos, start, end, prototype, questions); - } - - @Authenticated - @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) - public Result importGrades(Http.Request request) { - Http.MultipartFormData body = request.body().asMultipartFormData(); - Http.MultipartFormData.FilePart filePart = body.getFile("file"); - if (filePart == null) { - return notFound(); - } - File file = filePart.getRef().path().toFile(); - User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - boolean isAdmin = user.hasRole(Role.Name.ADMIN); - try { - csvBuilder.parseGrades(file, user, isAdmin ? Role.Name.ADMIN : Role.Name.TEACHER); - } catch (Exception e) { - logger.error("Failed to parse CSV file. Stack trace follows"); - e.printStackTrace(); - return internalServerError("sitnet_internal_error"); - } - return ok(); - } - - @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) - public Result getArchivedAttachments(Long eid, Optional start, Optional end) throws IOException { - Exam prototype = Ebean.find(Exam.class, eid); - if (prototype == null) { - return notFound(); - } - DateTime startDate = null; - DateTime endDate = null; - try { - DateFormat df = new SimpleDateFormat("dd.MM.yyyy"); - if (start.isPresent()) { - startDate = new DateTime(df.parse(start.get())).withTimeAtStartOfDay(); - } - if (end.isPresent()) { - endDate = new DateTime(df.parse(end.get())).withTimeAtStartOfDay().plusDays(1); - } - } catch (ParseException e) { - return badRequest(); - } - File tarball = File.createTempFile(eid.toString(), ".tar.gz"); - try ( - TarArchiveOutputStream aos = new TarArchiveOutputStream( - new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(tarball))) - ) - ) { - aos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); - createArchive(prototype, aos, startDate, endDate); - if (aos.getBytesWritten() == 0) { - return notFound("sitnet_no_attachments_to_archive"); - } - } catch (IOException e) { - logger.error("Failed in creating a tarball", e); - } - String contentDisposition = fileHandler.getContentDisposition(tarball); - byte[] data = fileHandler.read(tarball); - String body = Base64.getEncoder().encodeToString(data); - return ok(body).withHeader("Content-Disposition", contentDisposition); - } - private boolean isRejectedInLanguageInspection(Exam exam, User user, Exam.State newState) { LanguageInspection li = exam.getLanguageInspection(); return ( @@ -838,7 +639,7 @@ private Double round(Double src) { } private static Query createQuery() { - return Ebean + return DB .find(ExamParticipation.class) .fetch( "exam", @@ -847,12 +648,12 @@ private static Query createQuery() { .fetch("exam.course") .fetch("exam.course.organisation") .fetch("exam.course.gradeScale") - .fetch("exam.course.gradeScale.grades", new FetchConfig().query()) + .fetch("exam.course.gradeScale.grades", FetchConfig.ofQuery()) .fetch("exam.parent") .fetch("exam.parent.creator") .fetch("exam.parent.gradeScale") - .fetch("exam.parent.gradeScale.grades", new FetchConfig().query()) - .fetch("exam.parent.examOwners", new FetchConfig().query()) + .fetch("exam.parent.gradeScale.grades", FetchConfig.ofQuery()) + .fetch("exam.parent.examOwners", FetchConfig.ofQuery()) .fetch("exam.parent.examFeedbackConfig") .fetch("exam.examEnrolments") .fetch("exam.examEnrolments.reservation") @@ -869,7 +670,7 @@ private static Query createQuery() { .fetch( "exam.examSections.sectionQuestions", "sequenceNumber, maxScore, answerInstructions, evaluationCriteria, expectedWordCount, evaluationType", - new FetchConfig().query() + FetchConfig.ofQuery() ) .fetch("exam.examSections.sectionQuestions.question", "id, type, question, shared") .fetch("exam.examSections.sectionQuestions.question.attachment", "fileName") diff --git a/app/controllers/ReviewDocumentsController.scala b/app/controllers/ReviewDocumentsController.scala new file mode 100644 index 0000000000..7cce8be644 --- /dev/null +++ b/app/controllers/ReviewDocumentsController.scala @@ -0,0 +1,165 @@ +package controllers + +import io.ebean.DB +import models.questions.Question +import models.{Exam, Role} +import org.apache.commons.compress.archivers.ArchiveOutputStream +import org.apache.commons.compress.archivers.tar.{TarArchiveEntry, TarArchiveOutputStream} +import org.apache.commons.compress.utils.IOUtils +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormat +import org.jsoup.Jsoup +import play.api.Logging +import play.api.libs.Files +import play.api.mvc.* +import security.scala.Auth.{authorized, AuthenticatedAction} +import security.scala.{Auth, AuthExecutionContext} +import util.csv.CsvBuilder +import util.file.FileHandler +import util.scala.{DbApiHelper, JavaApiHelper} + +import java.io.* +import java.text.SimpleDateFormat +import java.util.Base64 +import java.util.zip.GZIPOutputStream +import javax.inject.Inject +import scala.collection.mutable +import scala.jdk.CollectionConverters.* +import scala.util.Using + +class ReviewDocumentsController @Inject() ( + val controllerComponents: ControllerComponents, + csvBuilder: CsvBuilder, + fileHandler: FileHandler, + authenticated: AuthenticatedAction, + implicit val ec: AuthExecutionContext +) extends BaseController + with JavaApiHelper + with DbApiHelper + with Logging: + + def importGrades: Action[MultipartFormData[Files.TemporaryFile]] = + authenticated(parse.multipartFormData) + .andThen(authorized(Seq(Role.Name.TEACHER, Role.Name.ADMIN))) { request => + request.body.file("file") match + case Some(file) => + val user = request.attrs(Auth.ATTR_USER) + val role = if user.hasRole(Role.Name.ADMIN) then Role.Name.ADMIN else Role.Name.TEACHER + try csvBuilder.parseGrades(file.ref.toFile, user, role) + catch + case e: Exception => + logger.error("Failed to parse CSV file. Stack trace follows", e) + InternalServerError("i18n_internal_error") + Ok + case None => NotFound + } + + def getArchivedAttachments( + eid: Long, + start: Option[String], + end: Option[String] + ): Action[AnyContent] = + Action.andThen(authorized(Seq(Role.Name.TEACHER, Role.Name.ADMIN))) { _ => + DB.find(classOf[Exam]).where().idEq(eid).find match + case Some(exam) => + val df = new SimpleDateFormat("dd.MM.yyyy") + val startDate = + start.map(txt => new DateTime(df.parse(txt)).withTimeAtStartOfDay) + val endDate = end.map(txt => new DateTime(df.parse(txt)).withTimeAtStartOfDay) + val tarball = File.createTempFile(eid.toString, ".tar.gz") + Using.resource( + new TarArchiveOutputStream( + new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(tarball))) + ) + ) { stream => + stream.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX) + createArchive(exam, stream, startDate, endDate) + } + val contentDisposition = fileHandler.getContentDisposition(tarball) + val data = fileHandler.read(tarball) + val body = Base64.getEncoder.encodeToString(data) + Ok(body).withHeaders(("Content-Disposition", contentDisposition)); + case None => NotFound + } + + private def isEligibleForArchiving(exam: Exam, start: Option[DateTime], end: Option[DateTime]) = + exam.hasState(Exam.State.ABORTED, Exam.State.REVIEW, Exam.State.REVIEW_STARTED) && + !(start.isDefined && exam.getCreated.isBefore( + start.get + )) && !(end.isDefined && exam.getCreated + .isAfter(end.get)) + + private def createArchive( + prototype: Exam, + aos: ArchiveOutputStream, + start: Option[DateTime], + end: Option[DateTime] + ): Unit = + val children = prototype.getChildren.asScala.filter(isEligibleForArchiving(_, start, end)) + val questions = mutable.LinkedHashMap.empty[Long, String] + for (exam <- children) + val id = Option(exam.getCreator.getUserIdentifier).getOrElse(exam.getCreator.getId.toString) + val uid = s"$id-${exam.getId}" + for (es <- exam.getExamSections.asScala) + val essays = es.getSectionQuestions.asScala + .filter(_.getQuestion.getType == Question.Type.EssayQuestion) + for (essay <- essays) + val questionId = Option(essay.getQuestion).flatMap(q => Option(q.getParent)) match + case None => essay.getQuestion.getId + case Some(p) => p.getId + val questionIdText = Option(essay.getQuestion).flatMap(q => Option(q.getParent)) match + case None => s"$questionId #original_question_removed" + case Some(p) => p.getId.toString + questions.put(questionId, essay.getQuestion.getQuestion) + val attachment = Option(essay.getEssayAnswer).flatMap(a => Option(a.getAttachment)) + val file = attachment.map(a => new File(a.getFilePath)) + file match + case Some(f) if f.exists => + val entryName = + s"${prototype.getId}/$questionIdText/$uid/${attachment.get.getFileName}" + addFileEntry(entryName, f, aos) + case _ => + if file.isDefined then + logger.warn( + s"Attachment ${attachment.get.getId} is not connected to a file on disk!" + ) + val entryName = s"${prototype.getId}/$questionId/$uid" + val entry = new TarArchiveEntry(entryName) + aos.putArchiveEntry(entry) + aos.closeArchiveEntry() + createSummaryFile(aos, start, end, prototype, questions.toMap) + + private def addFileEntry(name: String, file: File, os: ArchiveOutputStream): Unit = + val entry = new TarArchiveEntry(name) + entry.setSize(file.length) + os.putArchiveEntry(entry) + IOUtils.copy(new FileInputStream(file), os) + os.closeArchiveEntry() + + private def createSummaryFile( + aos: ArchiveOutputStream, + start: Option[DateTime], + end: Option[DateTime], + exam: Exam, + questions: Map[Long, String] + ): Unit = + val file = File.createTempFile("summary", ".txt") + Using.resource(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)))) { writer => + if start.isDefined || end.isDefined then + val dtf = DateTimeFormat.forPattern("dd.MM.yyyy") + val s = start.map(dtf.print).getOrElse("") + val e = end.map(dtf.print).getOrElse("") + writer.write(s"period: $s-$e") + writer.newLine() + writer.write(s"exam id: ${exam.getId}") + writer.newLine() + writer.write(s"exam name: ${exam.getName}") + writer.newLine() + writer.newLine() + writer.write("questions") + writer.newLine() + for ((k, v) <- questions) + writer.write(s"$k: ${Jsoup.parse(v).text}") + writer.newLine() + } + addFileEntry("summary.txt", file, aos) diff --git a/app/controllers/RoomController.java b/app/controllers/RoomController.java index e8f8c42a6d..39fed0c6a5 100644 --- a/app/controllers/RoomController.java +++ b/app/controllers/RoomController.java @@ -15,13 +15,13 @@ package controllers; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import controllers.base.BaseController; import controllers.iop.transfer.api.ExternalFacilityAPI; -import io.ebean.Ebean; +import exceptions.MalformedDataException; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.text.PathProperties; import java.net.MalformedURLException; @@ -31,7 +31,6 @@ import java.util.Optional; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; import javax.inject.Inject; import models.Accessibility; @@ -43,12 +42,15 @@ import models.User; import models.calendar.DefaultWorkingHours; import models.calendar.ExceptionWorkingHours; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.data.Form; import play.libs.Json; import play.mvc.Http; import play.mvc.Result; @@ -65,7 +67,7 @@ public class RoomController extends BaseController { private final ExternalFacilityAPI externalApi; protected ActorSystem system; private final DateTimeHandler dateTimeHandler; - private static final Logger.ALogger logger = Logger.of(RoomController.class); + private final Logger logger = LoggerFactory.getLogger(RoomController.class); private static final int EPOCH = 1970; @Inject @@ -115,7 +117,7 @@ private void asyncUpdateRemote(ExamRoom room) { @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN"), @Group("STUDENT") }) public Result getExamRooms(Http.Request request) { - ExpressionList query = Ebean + ExpressionList query = DB .find(ExamRoom.class) .fetch("accessibilities") .fetch("examMachines") @@ -139,7 +141,7 @@ public Result getExamRooms(Http.Request request) { @Restrict(@Group("ADMIN")) public Result getExamRoom(Long id) { - ExamRoom examRoom = Ebean.find(ExamRoom.class, id); + ExamRoom examRoom = DB.find(ExamRoom.class, id); if (examRoom == null) { return notFound("room not found"); } @@ -183,7 +185,7 @@ public CompletionStage updateExamRoom(Long id, Http.Request request) thr "expanded" ) .get(); - ExamRoom existing = Ebean.find(ExamRoom.class, id); + ExamRoom existing = DB.find(ExamRoom.class, id); if (existing == null) { return wrapAsPromise(notFound()); } @@ -209,12 +211,12 @@ public CompletionStage updateExamRoom(Long id, Http.Request request) thr @Restrict(@Group({ "ADMIN" })) public CompletionStage updateExamRoomAddress(Long id, Http.Request request) throws MalformedURLException { - MailAddress address = bindForm(MailAddress.class, request); - MailAddress existing = Ebean.find(MailAddress.class, id); + MailAddress address = bindAddress(request); + MailAddress existing = DB.find(MailAddress.class, id); if (existing == null) { return wrapAsPromise(notFound()); } - Optional room = Ebean.find(ExamRoom.class).where().eq("mailAddress", existing).findOneOrEmpty(); + Optional room = DB.find(ExamRoom.class).where().eq("mailAddress", existing).findOneOrEmpty(); if (room.isEmpty()) { return wrapAsPromise(notFound()); } @@ -225,6 +227,14 @@ public CompletionStage updateExamRoomAddress(Long id, Http.Request reque return updateRemote(room.get()); } + private MailAddress bindAddress(Http.Request request) { + final Form form = formFactory.form(MailAddress.class); + if (form.hasErrors()) { + throw new MalformedDataException(form.errorsAsJson().asText()); + } + return form.bindFromRequest(request).get(); + } + private DefaultWorkingHours parseWorkingHours(JsonNode root) { JsonNode node = root.get("workingHours"); DateTimeFormatter formatter = ISODateTimeFormat.dateTimeParser(); @@ -245,21 +255,18 @@ public Result updateExamRoomWorkingHours(Http.Request request) { for (JsonNode roomId : root.get("roomIds")) { roomIds.add(roomId.asLong()); } - List rooms = Ebean.find(ExamRoom.class).where().idIn(roomIds).findList(); + List rooms = DB.find(ExamRoom.class).where().idIn(roomIds).findList(); DefaultWorkingHours hours = parseWorkingHours(root); for (ExamRoom examRoom : rooms) { // Find out if there's overlap. Remove those - List existing = Ebean + List existing = DB .find(DefaultWorkingHours.class) .where() .eq("room", examRoom) .eq("weekday", hours.getWeekday()) .findList(); - List overlapping = existing - .stream() - .filter(dwh -> dwh.overlaps(hours)) - .collect(Collectors.toList()); - Ebean.deleteAll(overlapping); + List overlapping = existing.stream().filter(dwh -> dwh.overlaps(hours)).toList(); + DB.deleteAll(overlapping); examRoom.getDefaultWorkingHours().removeAll(overlapping); hours.setRoom(examRoom); @@ -277,8 +284,8 @@ public Result updateExamRoomWorkingHours(Http.Request request) { @Restrict(@Group({ "ADMIN" })) public Result removeExamRoomWorkingHours(Long roomId, Long id) { - DefaultWorkingHours dwh = Ebean.find(DefaultWorkingHours.class, id); - ExamRoom room = Ebean.find(ExamRoom.class, roomId); + DefaultWorkingHours dwh = DB.find(DefaultWorkingHours.class, id); + ExamRoom room = DB.find(ExamRoom.class, roomId); if (dwh == null || room == null) { return forbidden(); } @@ -296,18 +303,18 @@ public Result updateExamStartingHours(Http.Request request) { roomIds.add(roomId.asLong()); } - List rooms = Ebean.find(ExamRoom.class).where().idIn(roomIds).findList(); + List rooms = DB.find(ExamRoom.class).where().idIn(roomIds).findList(); for (ExamRoom examRoom : rooms) { if (examRoom == null) { return notFound(); } - List previous = Ebean + List previous = DB .find(ExamStartingHour.class) .where() .eq("room.id", examRoom.getId()) .findList(); - Ebean.deleteAll(previous); + DB.deleteAll(previous); JsonNode node = request.body().asJson(); DateTimeFormatter formatter = DateTimeFormat.forPattern("dd.MM.yyyy HH:mmZZ"); @@ -341,11 +348,8 @@ public Result addRoomExceptionHours(Http.Request request) { final JsonNode exceptionsNode = request.body().asJson().get("exceptions"); final JsonNode ids = request.body().asJson().get("roomIds"); - List roomIds = StreamSupport - .stream(ids.spliterator(), false) - .map(JsonNode::asLong) - .collect(Collectors.toList()); - List rooms = Ebean.find(ExamRoom.class).where().idIn(roomIds).findList(); + List roomIds = StreamSupport.stream(ids.spliterator(), false).map(JsonNode::asLong).toList(); + List rooms = DB.find(ExamRoom.class).where().idIn(roomIds).findList(); for (ExamRoom room : rooms) { for (JsonNode node : exceptionsNode) { ExceptionWorkingHours exception = parse(node); @@ -361,11 +365,7 @@ public Result addRoomExceptionHours(Http.Request request) { asyncUpdateRemote(room); } } - return ok( - Json.toJson( - rooms.stream().flatMap(r -> r.getCalendarExceptionEvents().stream()).collect(Collectors.toList()) - ) - ); + return ok(Json.toJson(rooms.stream().flatMap(r -> r.getCalendarExceptionEvents().stream()).toList())); } @Restrict(@Group({ "ADMIN" })) @@ -373,7 +373,7 @@ public Result updateExamRoomAccessibility(Long id, Http.Request request) { JsonNode json = request.body().asJson(); final List ids = Arrays.asList(json.get("ids").asText().split(",")); - ExamRoom room = Ebean.find(ExamRoom.class, id); + ExamRoom room = DB.find(ExamRoom.class, id); if (room == null) { return notFound(); } @@ -388,7 +388,7 @@ public Result updateExamRoomAccessibility(Long id, Http.Request request) { } catch (Exception ex) { break; } - Accessibility accessibility = Ebean.find(Accessibility.class, accessibilityId); + Accessibility accessibility = DB.find(Accessibility.class, accessibilityId); room.getAccessibilities().add(accessibility); room.save(); asyncUpdateRemote(room); @@ -399,8 +399,8 @@ public Result updateExamRoomAccessibility(Long id, Http.Request request) { @Restrict(@Group({ "ADMIN" })) public CompletionStage removeRoomExceptionHour(Long roomId, Long exceptionId) throws MalformedURLException { - ExceptionWorkingHours exception = Ebean.find(ExceptionWorkingHours.class, exceptionId); - ExamRoom room = Ebean.find(ExamRoom.class, roomId); + ExceptionWorkingHours exception = DB.find(ExceptionWorkingHours.class, exceptionId); + ExamRoom room = DB.find(ExamRoom.class, roomId); if (exception == null || room == null) { return wrapAsPromise(notFound()); } @@ -411,7 +411,7 @@ public CompletionStage removeRoomExceptionHour(Long roomId, Long excepti @Restrict(@Group({ "ADMIN" })) public CompletionStage inactivateExamRoom(Long id) throws MalformedURLException { - ExamRoom room = Ebean.find(ExamRoom.class, id); + ExamRoom room = DB.find(ExamRoom.class, id); if (room == null) { return wrapAsPromise(notFound()); } @@ -427,7 +427,7 @@ public CompletionStage inactivateExamRoom(Long id) throws MalformedURLEx @Restrict(@Group({ "ADMIN" })) public CompletionStage activateExamRoom(Long id) throws MalformedURLException { - ExamRoom room = Ebean.find(ExamRoom.class, id); + ExamRoom room = DB.find(ExamRoom.class, id); if (room == null) { return wrapAsPromise(notFound()); } diff --git a/app/controllers/RoomLike.java b/app/controllers/RoomLike.java index 2c735848cc..86e779b1f4 100644 --- a/app/controllers/RoomLike.java +++ b/app/controllers/RoomLike.java @@ -10,17 +10,16 @@ public interface RoomLike { String getRoomInstructionSV(); default String getRoomInstructions(Lang lang) { - String instructions; - switch (lang.code()) { - case "sv": - instructions = getRoomInstructionSV(); - return instructions == null ? getRoomInstruction() : instructions; - case "en": - instructions = getRoomInstructionEN(); - return instructions == null ? getRoomInstruction() : instructions; - case "fi": - default: - return getRoomInstruction(); - } + return switch (lang.code()) { + case "sv" -> { + String instructions = getRoomInstructionSV(); + yield instructions == null ? getRoomInstruction() : instructions; + } + case "en" -> { + String instructions = getRoomInstructionEN(); + yield instructions == null ? getRoomInstruction() : instructions; + } + default -> getRoomInstruction(); + }; } } diff --git a/app/controllers/SessionController.java b/app/controllers/SessionController.java index fdc411d8e4..f148299ba1 100644 --- a/app/controllers/SessionController.java +++ b/app/controllers/SessionController.java @@ -23,7 +23,7 @@ import controllers.base.BaseController; import controllers.iop.transfer.api.ExternalExamAPI; import exceptions.NotFoundException; -import io.ebean.Ebean; +import io.ebean.DB; import java.net.MalformedURLException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; @@ -45,16 +45,17 @@ import models.ExamEnrolment; import models.Language; import models.Organisation; +import models.Permission; import models.Reservation; import models.Role; import models.User; -import models.dto.Credentials; import org.apache.commons.codec.digest.DigestUtils; import org.joda.time.DateTime; import org.joda.time.Minutes; import org.joda.time.format.ISODateTimeFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.Environment; -import play.Logger; import play.libs.Json; import play.mvc.Http; import play.mvc.Result; @@ -70,7 +71,7 @@ public class SessionController extends BaseController { private final EnrolmentRepository enrolmentRepository; private final DateTimeHandler dateTimeHandler; - private static final Logger.ALogger logger = Logger.of(SessionController.class); + private final Logger logger = LoggerFactory.getLogger(SessionController.class); private static final int SESSION_TIMEOUT_MINUTES = 30; private static final String URN_PREFIX = "urn:"; @@ -106,18 +107,11 @@ public SessionController( @ActionMethod public CompletionStage login(Http.Request request) { - CompletionStage result; - switch (configReader.getLoginType()) { - case "HAKA": - result = hakaLogin(request); - break; - case "DEBUG": - result = devLogin(request); - break; - default: - result = wrapAsPromise(badRequest("login type not supported")); - } - return result; + return switch (configReader.getLoginType()) { + case "HAKA" -> hakaLogin(request); + case "DEBUG" -> devLogin(request); + default -> wrapAsPromise(badRequest("login type not supported")); + }; } private CompletionStage hakaLogin(Http.Request request) { @@ -128,22 +122,28 @@ private CompletionStage hakaLogin(Http.Request request) { String eppn = id.get(); Reservation externalReservation = getUpcomingExternalReservation(eppn); boolean isTemporaryVisitor = externalReservation != null; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); - boolean newUser = user == null; + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); try { - if (newUser) { + if (user == null) { user = createNewUser(eppn, request, isTemporaryVisitor); } else { updateUser(user, request); } } catch (NotFoundException | AddressException e) { + logger.error("Login failed", e); + String headers = request + .headers() + .asMap() + .entrySet() + .stream() + .map(entry -> String.format("%s: %s", entry.getKey(), entry.getValue())) + .collect(Collectors.joining()); + logger.error("Received following request headers: {}", headers); return wrapAsPromise(badRequest(e.getMessage())); } user.setLastLogin(new Date()); user.save(); - if (newUser) { - associateWithPreEnrolments(user); - } + associateWithPreEnrolments(user); return handleExternalReservationAndCreateSession(user, externalReservation, request); } @@ -151,21 +151,17 @@ private CompletionStage devLogin(Http.Request request) { if (!environment.isDev()) { return wrapAsPromise(unauthorized("Developer login mode not allowed while in production!")); } - Credentials credentials = bindForm(Credentials.class, request); - logger.debug("User login with username: {}", credentials.getUsername() + "@funet.fi"); - if (credentials.getPassword() == null || credentials.getUsername() == null) { - return wrapAsPromise(unauthorized("sitnet_error_unauthenticated")); + var username = request.body().asJson().get("username").asText(); + var password = request.body().asJson().get("password").asText(); + logger.debug("User login with username: {}", username + "@funet.fi"); + if (password == null || username == null) { + return wrapAsPromise(unauthorized("i18n_error_unauthenticated")); } - String pwd = DigestUtils.md5Hex(credentials.getPassword()); - User user = Ebean - .find(User.class) - .where() - .eq("eppn", credentials.getUsername() + "@funet.fi") - .eq("password", pwd) - .findOne(); + String pwd = DigestUtils.md5Hex(password); + User user = DB.find(User.class).where().eq("eppn", username + "@funet.fi").eq("password", pwd).findOne(); if (user == null) { - return wrapAsPromise(unauthorized("sitnet_error_unauthenticated")); + return wrapAsPromise(unauthorized("i18n_error_unauthenticated")); } user.setLastLogin(new Date()); user.update(); @@ -197,7 +193,7 @@ private boolean isUserPreEnrolled(String mail, User user) { private void associateWithPreEnrolments(User user) { // Associate pre-enrolment with a real user now that he/she is logged in - Ebean + DB .find(ExamEnrolment.class) .where() .isNotNull("preEnrolledUserEmail") @@ -215,7 +211,7 @@ private Reservation getUpcomingExternalReservation(String eppn) { DateTime now = dateTimeHandler.adjustDST(new DateTime()); int lookAheadMinutes = Minutes.minutesBetween(now, now.plusDays(1).withMillisOfDay(0)).getMinutes(); DateTime future = now.plusMinutes(lookAheadMinutes); - List reservations = Ebean + List reservations = DB .find(Reservation.class) .where() .eq("externalUserRef", eppn) @@ -224,12 +220,12 @@ private Reservation getUpcomingExternalReservation(String eppn) { .gt("endAt", now) .orderBy("startAt") .findList(); - return reservations.isEmpty() ? null : reservations.get(0); + return reservations.isEmpty() ? null : reservations.getFirst(); } private CompletionStage handleExternalReservation(User user, Reservation reservation) throws MalformedURLException { - ExamEnrolment enrolment = Ebean.find(ExamEnrolment.class).where().eq("reservation", reservation).findOne(); + ExamEnrolment enrolment = DB.find(ExamEnrolment.class).where().eq("reservation", reservation).findOne(); if (enrolment != null) { // already imported return wrapAsPromise(ok()); @@ -241,16 +237,17 @@ private CompletionStage handleExternalReservation(User user, Reservation .thenApplyAsync(e -> e == null ? internalServerError() : ok()); } - private static Language getLanguage(String code) { + private Language getLanguage(String code) { Language language = null; if (code != null) { // for example: en-US -> en String lcCode = code.split("-")[0].toLowerCase(); - language = Ebean.find(Language.class, lcCode); + var lang = configReader.getSupportedLanguages().contains(lcCode) ? lcCode : "en"; + language = DB.find(Language.class, lang); } if (language == null) { // Default to English - language = Ebean.find(Language.class, "en"); + language = DB.find(Language.class, "en"); } return language; } @@ -325,7 +322,7 @@ private String parseGivenName(Http.Request request) { } private Organisation findOrganisation(String attribute) { - return Ebean.find(Organisation.class).where().eq("code", attribute).findOne(); + return DB.find(Organisation.class).where().eq("code", attribute).findOne(); } private void updateUser(User user, Http.Request request) throws AddressException { @@ -335,6 +332,15 @@ private void updateUser(User user, Http.Request request) throws AddressException user.setUserIdentifier( parse(request.header("schacPersonalUniqueCode").orElse("")).map(this::parseUserIdentifier).orElse(null) ); + // Grant BYOD permission automatically for teachers if configuration so mandates + if (user.hasRole(Role.Name.TEACHER) && configReader.isByodExamCreationPermissionGrantedForNewUsers()) { + Permission permission = DB + .find(Permission.class) + .where() + .eq("type", Permission.Type.CAN_CREATE_BYOD_EXAM) + .findOne(); + user.getPermissions().add(permission); + } user.setEmail( parse(request.header("mail").orElse("")) .flatMap(this::validateEmail) @@ -371,19 +377,19 @@ private CompletionStage createSession(User user, boolean isTemporaryVisi payload.put("id", user.getId().toString()); payload.put("email", user.getEmail()); if (!user.getPermissions().isEmpty()) { - // For now we support just a single permission - payload.put("permissions", user.getPermissions().get(0).getValue()); + // For now, we support just a single permission + payload.put("permissions", user.getPermissions().getFirst().getValue()); } // If (regular) user has just one role, set it as the one used for login if (user.getRoles().size() == 1 && !isTemporaryVisitor) { - payload.put("role", user.getRoles().get(0).getName()); + payload.put("role", user.getRoles().getFirst().getName()); } List roles = isTemporaryVisitor - ? Ebean.find(Role.class).where().eq("name", Role.Name.STUDENT.toString()).findList() + ? DB.find(Role.class).where().eq("name", Role.Name.STUDENT.toString()).findList() : user.getRoles(); if (isTemporaryVisitor) { payload.put("visitingStudent", "true"); - payload.put("role", roles.get(0).getName()); // forced login as student + payload.put("role", roles.getFirst().getName()); // forced login as student } ObjectNode result = Json.newObject(); result.put("id", user.getId()); @@ -401,13 +407,11 @@ private CompletionStage createSession(User user, boolean isTemporaryVisi // prints HAKA attributes, used for debugging @ActionMethod public Result getAttributes(Http.Request request) { - Http.Headers attributes = request.getHeaders(); + Http.Headers attributes = request.headers(); ObjectNode node = Json.newObject(); - for (Map.Entry> entry : attributes.asMap().entrySet()) { node.put(entry.getKey(), String.join(", ", entry.getValue())); } - return ok(node); } @@ -422,7 +426,7 @@ private Set parseRoles(String attribute, boolean ignoreRoleNotFound) throw } } if (userRoles.isEmpty() && !ignoreRoleNotFound) { - throw new NotFoundException("sitnet_error_role_not_found " + attribute); + throw new NotFoundException("i18n_error_role_not_found " + attribute); } return userRoles; } @@ -432,7 +436,7 @@ public Result logout(Http.Request request) { Map session = request.session().data(); if (!session.isEmpty()) { Long userId = Long.parseLong(session.get("id")); - User user = Ebean.find(User.class, userId); + User user = DB.find(User.class, userId); if (user != null && user.getLogoutUrl() != null) { ObjectNode node = Json.newObject(); node.put("logoutUrl", user.getLogoutUrl()); @@ -449,11 +453,11 @@ public CompletionStage setLoginRole(String roleName, Http.Request reques if (session.get("id").isEmpty()) { return wrapAsPromise(unauthorized()); } - User user = Ebean.find(User.class, Long.parseLong(session.get("id").get())); + User user = DB.find(User.class, Long.parseLong(session.get("id").get())); if (user == null) { return wrapAsPromise(notFound()); } - Role role = Ebean.find(Role.class).where().eq("name", roleName).findOne(); + Role role = DB.find(Role.class).where().eq("name", roleName).findOne(); if (role == null) { return wrapAsPromise(notFound()); } diff --git a/app/controllers/SettingsController.java b/app/controllers/SettingsController.java index 2001506749..04c922d3ef 100644 --- a/app/controllers/SettingsController.java +++ b/app/controllers/SettingsController.java @@ -23,10 +23,11 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.ActionMethod; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Update; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.concurrent.CompletionStage; @@ -58,16 +59,11 @@ public SettingsController(Environment environment, ConfigReader configReader, WS } public static GeneralSettings get(String name) { - return Ebean - .find(GeneralSettings.class) - .where() - .eq("name", name) - .findOneOrEmpty() - .orElse(new GeneralSettings()); + return DB.find(GeneralSettings.class).where().eq("name", name).findOneOrEmpty().orElse(new GeneralSettings()); } public static GeneralSettings getOrCreateSettings(String name, String value, String defaultValue) { - GeneralSettings gs = Ebean.find(GeneralSettings.class).where().eq("name", name).findOne(); + GeneralSettings gs = DB.find(GeneralSettings.class).where().eq("name", name).findOne(); if (gs == null) { gs = new GeneralSettings(); gs.setName(name); @@ -103,12 +99,12 @@ public Result getReservationWindowSize() { @Restrict({ @Group("ADMIN"), @Group("TEACHER"), @Group("STUDENT") }) public CompletionStage getMaturityInstructions(String lang, Optional hash) throws IOException { - Language language = Ebean.find(Language.class, lang); + Language language = DB.find(Language.class, lang); if (language == null) { return wrapAsPromise(badRequest("Language not supported")); } if (hash.isPresent()) { - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .eq("externalExam.hash", hash.get()) @@ -122,7 +118,7 @@ public CompletionStage getMaturityInstructions(String lang, Optional { JsonNode root = response.asJson(); - if (response.getStatus() != 200) { + if (response.getStatus() != Http.Status.OK) { return internalServerError(root.get("message").asText("Connection refused")); } return ok(root); @@ -135,7 +131,7 @@ public CompletionStage getMaturityInstructions(String lang, Optional update = Ebean.createUpdate(User.class, updStatement); + Update update = DB.createUpdate(User.class, updStatement); update.set("hasNot", false); update.execute(); @@ -188,13 +184,6 @@ public Result getMaxFilesize() { return ok(Json.toJson(node)); } - @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) - public Result getExamMaxDate() { - ObjectNode node = Json.newObject(); - node.put("maxDate", configReader.getExamMaxDate().toString()); - return ok(Json.toJson(node)); - } - @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result getExamDurations() { ObjectNode node = Json.newObject(); @@ -336,7 +325,16 @@ public Result getCourseCodePrefix() { return ok(Json.toJson(node)); } + @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) + public Result getByodMaxParticipants() { + ObjectNode node = Json.newObject(); + node.put("max", configReader.getMaxByodExaminationParticipantCount()); + return ok(Json.toJson(node)); + } + private URL parseExternalUrl(String reservationRef) throws MalformedURLException { - return new URL(configReader.getIopHost() + String.format("/api/enrolments/%s/instructions", reservationRef)); + return URI + .create(configReader.getIopHost() + String.format("/api/enrolments/%s/instructions", reservationRef)) + .toURL(); } } diff --git a/app/controllers/StatisticsController.java b/app/controllers/StatisticsController.java index 9057259423..1e65d47968 100644 --- a/app/controllers/StatisticsController.java +++ b/app/controllers/StatisticsController.java @@ -18,7 +18,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -41,7 +41,8 @@ import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Result; public class StatisticsController extends BaseController { @@ -49,11 +50,11 @@ public class StatisticsController extends BaseController { private static final DateTimeFormatter DTF = DateTimeFormat.forPattern("dd.MM.yyyy"); private static final String XLSX_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - private static final Logger.ALogger logger = Logger.of(StatisticsController.class); + private final Logger logger = LoggerFactory.getLogger(StatisticsController.class); @Restrict({ @Group("ADMIN") }) public Result getStudents() { - List students = Ebean + List students = DB .find(User.class) .select("id, firstName, lastName") .where() @@ -64,7 +65,7 @@ public Result getStudents() { @Restrict({ @Group("ADMIN") }) public Result getExamNames() { - List exams = Ebean + List exams = DB .find(Exam.class) .select("id, name") .fetch("course", "id, name, code") @@ -88,8 +89,8 @@ private static Result examToExcel(Exam exam) throws IOException { values.put("Course unit type", forceNotNull(exam.getCourse().getCourseUnitType())); values.put("Course level", forceNotNull(exam.getCourse().getLevel())); values.put("Created", ISODateTimeFormat.date().print(new DateTime(exam.getCreated()))); - values.put("Begins", ISODateTimeFormat.date().print(new DateTime(exam.getExamActiveStartDate()))); - values.put("Ends", ISODateTimeFormat.date().print(new DateTime(exam.getExamActiveEndDate()))); + values.put("Begins", ISODateTimeFormat.date().print(new DateTime(exam.getPeriodStart()))); + values.put("Ends", ISODateTimeFormat.date().print(new DateTime(exam.getPeriodEnd()))); values.put("Duration", exam.getDuration() == null ? "N/A" : exam.getDuration().toString()); values.put("Grade scale", exam.getGradeScale() == null ? "N/A" : exam.getGradeScale().getDescription()); values.put("State", exam.getState().toString()); @@ -117,7 +118,7 @@ private static Result examToExcel(Exam exam) throws IOException { } private static Result examToJson(Exam exam) { - String content = Ebean.json().toJson(exam); + String content = DB.json().toJson(exam); return ok(content) .as("application/json") .withHeader("Content-Disposition", "attachment; filename=\"exams.json\""); @@ -132,26 +133,23 @@ private void createRow(Sheet sheet, String[] data, List items, T parent) @Restrict({ @Group("ADMIN") }) public Result getExam(Long id, String reportType) throws IOException { - Exam exam = Ebean.find(Exam.class).where().idEq(id).isNotNull("course").findOne(); + Exam exam = DB.find(Exam.class).where().idEq(id).isNotNull("course").findOne(); if (exam == null) { return notFound(); } - switch (reportType) { - case "xlsx": - return examToExcel(exam); - case "json": - return examToJson(exam); - default: - return badRequest("invalid type: " + reportType); - } + return switch (reportType) { + case "xlsx" -> examToExcel(exam); + case "json" -> examToJson(exam); + default -> badRequest("invalid type: " + reportType); + }; } @Restrict({ @Group("ADMIN") }) public Result getTeacherExamsByDate(Long uid, String from, String to) throws IOException { final DateTime start = DateTime.parse(from, DTF); final DateTime end = DateTime.parse(to, DTF); - List exams = Ebean + List exams = DB .find(Exam.class) .fetch("creator") .fetch("examType") @@ -186,18 +184,10 @@ public Result getTeacherExamsByDate(Long uid, String from, String to) throws IOE int logged = 0; for (Exam child : parent.getChildren()) { switch (child.getState()) { - case REVIEW: - case REVIEW_STARTED: - inReview++; - break; - case GRADED: - graded++; - break; - case GRADED_LOGGED: - logged++; - break; - default: - break; + case REVIEW, REVIEW_STARTED -> inReview++; + case GRADED -> graded++; + case GRADED_LOGGED -> logged++; + default -> {} } } String[] data = new String[10]; @@ -208,8 +198,8 @@ public Result getTeacherExamsByDate(Long uid, String from, String to) throws IOE data[4] = String.format( "%s - %s", - ISODateTimeFormat.date().print(new DateTime(parent.getExamActiveStartDate())), - ISODateTimeFormat.date().print(new DateTime(parent.getExamActiveEndDate())) + ISODateTimeFormat.date().print(new DateTime(parent.getPeriodStart())), + ISODateTimeFormat.date().print(new DateTime(parent.getPeriodEnd())) ); data[5] = parent.getCourse().getCredits() == null ? "" : Double.toString(parent.getCourse().getCredits()); data[6] = parent.getExamType().getType(); @@ -227,7 +217,7 @@ public Result getTeacherExamsByDate(Long uid, String from, String to) throws IOE @Restrict({ @Group("ADMIN") }) public Result getExamEnrollments(Long id) throws IOException { - Exam proto = Ebean + Exam proto = DB .find(Exam.class) .fetch("examEnrolments") .fetch("examEnrolments.user") @@ -238,7 +228,7 @@ public Result getExamEnrollments(Long id) throws IOException { .isNull("parent") .findOne(); if (proto == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Workbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet("enrolments"); @@ -278,7 +268,7 @@ private String parse(Supplier supplier) { public Result getReviewsByDate(String from, String to) throws IOException { final DateTime start = DateTime.parse(from, DTF); final DateTime end = DateTime.parse(to, DTF); - List exams = Ebean + List exams = DB .find(Exam.class) .fetch("course") .where() @@ -334,7 +324,7 @@ public Result getReservationsForRoomByDate(Long roomId, String from, String to) final DateTime start = DateTime.parse(from, DTF); final DateTime end = DateTime.parse(to, DTF); - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .fetch("user") .fetch("exam") @@ -391,7 +381,7 @@ public Result getReservationsForRoomByDate(Long roomId, String from, String to) .toArray(new String[0]); createRow(sheet, data, enrolments, e); } - IntStream.range(0, 17).forEach(i -> sheet.autoSizeColumn(i, true)); + IntStream.range(0, headers.length + 1).forEach(i -> sheet.autoSizeColumn(i, true)); return ok(encode(wb)) .as(XLSX_MIME) .withHeader("Content-Disposition", "attachment; filename=\"reservations.xlsx\""); @@ -402,7 +392,7 @@ public Result reportAllExams(String from, String to) throws IOException { final DateTime start = DateTime.parse(from, DTF); final DateTime end = DateTime.parse(to, DTF); - List participations = Ebean + List participations = DB .find(ExamParticipation.class) .fetch("exam") .where() @@ -427,9 +417,9 @@ public Result reportStudentActivity(Long studentId, String from, String to) thro final DateTime start = DateTime.parse(from, DTF); final DateTime end = DateTime.parse(to, DTF); - User student = Ebean.find(User.class, studentId); + User student = DB.find(User.class, studentId); if (student == null) { - return notFound("sitnet_error_not_found"); + return notFound("i18n_error_not_found"); } Workbook wb = new XSSFWorkbook(); Sheet studentSheet = wb.createSheet("student"); @@ -443,7 +433,7 @@ public Result reportStudentActivity(Long studentId, String from, String to) thro dataRow.createCell(index++).setCellValue(student.getEmail()); dataRow.createCell(index).setCellValue(student.getLanguage().getCode()); - List participations = Ebean + List participations = DB .find(ExamParticipation.class) .fetch("exam") .fetch("reservation") diff --git a/app/controllers/StudentActionsController.java b/app/controllers/StudentActionsController.java index d7e4d1003e..19b2f070cf 100644 --- a/app/controllers/StudentActionsController.java +++ b/app/controllers/StudentActionsController.java @@ -19,7 +19,7 @@ import be.objectify.deadbolt.java.actions.Restrict; import controllers.iop.collaboration.impl.CollaborationController; import impl.ExternalCourseHandler; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.FetchConfig; import io.ebean.Model; @@ -36,7 +36,6 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletionStage; -import java.util.stream.Collectors; import javax.inject.Inject; import models.Exam; import models.ExamEnrolment; @@ -47,7 +46,7 @@ import org.joda.time.DateTime; import play.i18n.MessagesApi; import play.libs.Json; -import play.libs.concurrent.HttpExecutionContext; +import play.libs.concurrent.ClassLoaderExecutionContext; import play.mvc.Http; import play.mvc.Result; import repository.EnrolmentRepository; @@ -64,7 +63,7 @@ public class StudentActionsController extends CollaborationController { private final boolean permCheckActive; - private final HttpExecutionContext ec; + private final ClassLoaderExecutionContext ec; private final ExternalCourseHandler externalCourseHandler; private final EnrolmentRepository enrolmentRepository; private final ByodConfigHandler byodConfigHandler; @@ -75,7 +74,7 @@ public class StudentActionsController extends CollaborationController { @Inject public StudentActionsController( - HttpExecutionContext ec, + ClassLoaderExecutionContext ec, ExternalCourseHandler courseHandler, EnrolmentRepository enrolmentRepository, ConfigReader configReader, @@ -96,7 +95,7 @@ public StudentActionsController( @Authenticated public Result getExamFeedback(Long id, Http.Request request) { - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("creator", "firstName, lastName, email") .fetch("course", "code, name, credits") @@ -127,14 +126,14 @@ public Result getExamFeedback(Long id, Http.Request request) { .endJunction() .findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } return ok(exam); } @Authenticated public Result getExamScore(Long eid, Http.Request request) { - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("examSections.sectionQuestions.question") .where() @@ -151,7 +150,7 @@ public Result getExamScore(Long eid, Http.Request request) { .endJunction() .findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } exam.setMaxScore(); exam.setApprovedAnswerCount(); @@ -163,7 +162,7 @@ public Result getExamScore(Long eid, Http.Request request) { @Authenticated public Result getExamScoreReport(Long eid, Http.Request request) { - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("examParticipation.user") .fetch("examSections.sectionQuestions.question") @@ -183,7 +182,7 @@ public Result getExamScoreReport(Long eid, Http.Request request) { .findOne(); if (exam == null || exam.getExamParticipation() == null || exam.getExamParticipation().getUser() == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } User student = exam.getExamParticipation().getUser(); @@ -191,7 +190,7 @@ public Result getExamScoreReport(Long eid, Http.Request request) { try { bos = excelBuilder.buildStudentReport(exam, student, messagesApi); } catch (IOException e) { - return internalServerError("sitnet_error_creating_excel_file"); + return internalServerError("i18n_error_creating_excel_file"); } return ok(Base64.getEncoder().encodeToString(bos.toByteArray())) .withHeader("Content-Disposition", "attachment; filename=\"exam_records.xlsx\"") @@ -199,7 +198,7 @@ public Result getExamScoreReport(Long eid, Http.Request request) { } private Set getNoShows(User user, String filter) { - ExpressionList noShows = Ebean + ExpressionList noShows = DB .find(ExamEnrolment.class) .fetch("exam", "id, state, name") .fetch("exam.course", "code, name") @@ -229,7 +228,7 @@ private Set getNoShows(User user, String filter) { @Authenticated public Result getFinishedExams(Optional filter, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean + ExpressionList query = DB .find(ExamParticipation.class) .fetch("exam", "id, state, name, autoEvaluationNotified, anonymous, gradeless") .fetch("exam.creator", "id") @@ -265,14 +264,14 @@ public Result getFinishedExams(Optional filter, Http.Request request) { @Authenticated public CompletionStage getEnrolment(Long eid, Http.Request request) throws IOException { - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("exam") .fetch("externalExam") .fetch("collaborativeExam") .fetch("exam.course", "name, code") - .fetch("exam.examOwners", "firstName, lastName", new FetchConfig().query()) - .fetch("exam.examInspections", new FetchConfig().query()) + .fetch("exam.examOwners", "firstName, lastName", FetchConfig.ofQuery()) + .fetch("exam.examInspections", FetchConfig.ofQuery()) .fetch("exam.examInspections.user", "firstName, lastName") .fetch("user", "id") .fetch("reservation", "startAt, endAt") @@ -301,7 +300,7 @@ public CompletionStage getEnrolment(Long eid, Http.Request request) thro return downloadExam(enrolment.getCollaborativeExam()) .thenComposeAsync(result -> { if (result.isPresent()) { - // Bit of a hack so that we can pass the external exam as an ordinary one so the UI does not need to care + // A bit of a hack so that we can pass the external exam as an ordinary one so the UI does not need to care // Works in this particular use case Exam exam = result.get(); enrolment.setExam(exam); @@ -312,7 +311,7 @@ public CompletionStage getEnrolment(Long eid, Http.Request request) thro }); } if (enrolment.getExternalExam() != null) { - // Bit of a hack so that we can pass the external exam as an ordinary one so the UI does not need to care + // A bit of a hack so that we can pass the external exam as an ordinary one so the UI does not need to care // Works in this particular use case Exam exam = enrolment.getExternalExam().deserialize(); enrolment.setExternalExam(null); @@ -330,13 +329,13 @@ public CompletionStage getEnrolmentsForUser(Http.Request request) { @Authenticated public Result getExamConfigFile(Long enrolmentId, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Optional oee = Ebean + Optional oee = DB .find(ExamEnrolment.class) .where() .idEq(enrolmentId) .eq("user", user) .eq("exam.implementation", Exam.Implementation.CLIENT_AUTH) - .eq("exam.state", Exam.State.PUBLISHED) + .in("exam.state", Exam.State.PUBLISHED, Exam.State.STUDENT_STARTED) .isNotNull("examinationEventConfiguration") .findOneOrEmpty(); if (oee.isEmpty()) { @@ -345,6 +344,10 @@ public Result getExamConfigFile(Long enrolmentId, Http.Request request) { String examName = oee.get().getExam().getName(); ExaminationEventConfiguration eec = oee.get().getExaminationEventConfiguration(); String fileName = examName.replace(" ", "-"); + String quitPassword = byodConfigHandler.getPlaintextPassword( + eec.getEncryptedQuitPassword(), + eec.getQuitPasswordSalt() + ); File file; try { file = File.createTempFile(fileName, ".seb"); @@ -352,7 +355,8 @@ public Result getExamConfigFile(Long enrolmentId, Http.Request request) { byte[] data = byodConfigHandler.getExamConfig( eec.getHash(), eec.getEncryptedSettingsPassword(), - eec.getSettingsPasswordSalt() + eec.getSettingsPasswordSalt(), + quitPassword ); fos.write(data); fos.close(); @@ -368,7 +372,7 @@ public Result getExamConfigFile(Long enrolmentId, Http.Request request) { @Authenticated public Result getExamInfo(Long eid, Http.Request request) { - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .fetch("course", "code, name") .fetch("examSections") @@ -379,7 +383,7 @@ public Result getExamInfo(Long eid, Http.Request request) { .eq("examEnrolments.user", request.attrs().get(Attrs.AUTHENTICATED_USER)) .findOne(); if (exam == null) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } return ok(exam); @@ -404,19 +408,19 @@ public CompletionStage listAvailableExams(final Optional filter, } private Result listExams(String filter, Collection courseCodes) { - ExpressionList query = Ebean + ExpressionList query = DB .find(Exam.class) - .select("id, name, duration, examActiveStartDate, examActiveEndDate, enrollInstruction, implementation") + .select("id, name, duration, periodStart, periodEnd, enrollInstruction, implementation") .fetch("course", "code, name") .fetch("examOwners", "firstName, lastName") .fetch("examInspections.user", "firstName, lastName") - .fetch("examLanguages", "code, name", new FetchConfig().query()) + .fetch("examLanguages", "code, name", FetchConfig.ofQuery()) .fetch("creator", "firstName, lastName") .fetch("examinationEventConfigurations.examinationEvent") .where() .eq("state", Exam.State.PUBLISHED) .eq("executionType.type", ExamExecutionType.Type.PUBLIC.toString()) - .gt("examActiveEndDate", DateTime.now().toDate()); + .gt("periodEnd", DateTime.now().toDate()); if (!courseCodes.isEmpty()) { query.in("course.code", courseCodes); } @@ -444,7 +448,7 @@ private Result listExams(String filter, Collection courseCodes) { .map(ExaminationEventConfiguration::getExaminationEvent) .anyMatch(ee -> ee.getStart().isAfter(DateTime.now())) ) - .collect(Collectors.toList()); + .toList(); return ok(exams); } } diff --git a/app/controllers/TagController.java b/app/controllers/TagController.java index 27aa1f25bd..351357b787 100644 --- a/app/controllers/TagController.java +++ b/app/controllers/TagController.java @@ -17,16 +17,19 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; +import com.fasterxml.jackson.databind.JsonNode; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.text.PathProperties; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.StreamSupport; import models.Role; import models.Tag; import models.User; +import models.questions.Question; import play.mvc.Http; import play.mvc.Result; import sanitizers.Attrs; @@ -38,13 +41,14 @@ public class TagController extends BaseController { @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result listTags( Optional filter, - Optional> examIds, Optional> courseIds, + Optional> examIds, Optional> sectionIds, + Optional> ownerIds, Http.Request request ) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExpressionList query = Ebean.find(Tag.class).where(); + ExpressionList query = DB.find(Tag.class).where(); if (!user.hasRole(Role.Name.ADMIN)) { query = query.where().eq("creator.id", user.getId()); } @@ -61,7 +65,29 @@ public Result listTags( if (sectionIds.isPresent() && !sectionIds.get().isEmpty()) { query = query.in("questions.examSectionQuestions.examSection.id", sectionIds.get()); } + if (ownerIds.isPresent() && !ownerIds.get().isEmpty()) { + query = query.in("questions.questionOwners.id", ownerIds.get()); + } Set tags = query.findSet(); - return ok(tags, PathProperties.parse("(*, creator(id))")); + return ok(tags, PathProperties.parse("(*, creator(id), questions(id))")); + } + + @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) + public Result addTagToQuestions(Http.Request request) { + JsonNode body = request.body().asJson(); + List questionIds = StreamSupport + .stream(body.get("questionIds").spliterator(), false) + .map(JsonNode::asLong) + .toList(); + Long tagId = body.get("tagId").asLong(); + List questions = DB.find(Question.class).where().idIn(questionIds).findList(); + Tag tag = DB.find(Tag.class, tagId); + questions.forEach(question -> { + if (!question.getTags().contains(tag)) { + question.getTags().add(tag); + question.update(); + } + }); + return ok(); } } diff --git a/app/controllers/TimeController.java b/app/controllers/TimeController.java index 351d271f47..331a4bf6fb 100644 --- a/app/controllers/TimeController.java +++ b/app/controllers/TimeController.java @@ -18,7 +18,7 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.IOException; import javax.inject.Inject; import models.Exam; @@ -45,7 +45,7 @@ public TimeController(DateTimeHandler dateTimeHandler) { @Restrict({ @Group("STUDENT") }) public Result getRemainingExamTime(String hash, Http.Request request) throws IOException { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("externalExam") .where() diff --git a/app/controllers/UserController.java b/app/controllers/UserController.java index 763760cc4e..a9ebe43620 100644 --- a/app/controllers/UserController.java +++ b/app/controllers/UserController.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.Query; import io.ebean.text.PathProperties; @@ -28,7 +28,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import models.ExamEnrolment; import models.ExamInspection; import models.Language; @@ -50,14 +49,14 @@ public class UserController extends BaseController { @Restrict({ @Group("ADMIN") }) public Result listPermissions() { - return ok(Ebean.find(Permission.class).findList()); + return ok(DB.find(Permission.class).findList()); } @Restrict({ @Group("ADMIN") }) public Result grantUserPermission(Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); String permissionString = df.get("permission"); - User user = Ebean.find(User.class, df.get("id")); + User user = DB.find(User.class, df.get("id")); if (user == null) { return notFound(); } @@ -68,7 +67,7 @@ public Result grantUserPermission(Http.Request request) { } catch (IllegalArgumentException e) { return badRequest(); } - Permission permission = Ebean.find(Permission.class).where().eq("type", type).findOne(); + Permission permission = DB.find(Permission.class).where().eq("type", type).findOne(); user.getPermissions().add(permission); user.update(); } @@ -79,12 +78,12 @@ public Result grantUserPermission(Http.Request request) { public Result revokeUserPermission(Http.Request request) { DynamicForm df = formFactory.form().bindFromRequest(request); String permissionString = df.get("permission"); - User user = Ebean.find(User.class, df.get("id")); + User user = DB.find(User.class, df.get("id")); if (user == null) { return notFound(); } if (user.getPermissions().stream().anyMatch(p -> p.getValue().equals(permissionString))) { - Permission permission = Ebean + Permission permission = DB .find(Permission.class) .where() .eq("type", Permission.Type.valueOf(permissionString)) @@ -98,7 +97,7 @@ public Result revokeUserPermission(Http.Request request) { @Restrict({ @Group("ADMIN") }) public Result findUsers(Optional filter) { PathProperties pp = PathProperties.parse("(*, roles(*), permissions(*))"); - Query query = Ebean.find(User.class); + Query query = DB.find(User.class); pp.apply(query); List results; if (filter.isPresent()) { @@ -121,14 +120,14 @@ public Result findUsers(Optional filter) { @Restrict({ @Group("ADMIN") }) public Result addRole(Long uid, String roleName) { - User user = Ebean.find(User.class, uid); + User user = DB.find(User.class, uid); if (user == null) { - return notFound("sitnet_user_not_found"); + return notFound("i18n_user_not_found"); } if (user.getRoles().stream().noneMatch(r -> r.getName().equals(roleName))) { - Role role = Ebean.find(Role.class).where().eq("name", roleName).findOne(); + Role role = DB.find(Role.class).where().eq("name", roleName).findOne(); if (role == null) { - return notFound("sitnet_role_not_found"); + return notFound("i18n_role_not_found"); } user.getRoles().add(role); user.update(); @@ -138,14 +137,14 @@ public Result addRole(Long uid, String roleName) { @Restrict({ @Group("ADMIN") }) public Result removeRole(Long uid, String roleName) { - User user = Ebean.find(User.class, uid); + User user = DB.find(User.class, uid); if (user == null) { - return notFound("sitnet_user_not_found"); + return notFound("i18n_user_not_found"); } if (user.getRoles().stream().anyMatch(r -> r.getName().equals(roleName))) { - Role role = Ebean.find(Role.class).where().eq("name", roleName).findOne(); + Role role = DB.find(Role.class).where().eq("name", roleName).findOne(); if (role == null) { - return notFound("sitnet_role_not_found"); + return notFound("i18n_role_not_found"); } user.getRoles().remove(role); user.update(); @@ -155,20 +154,9 @@ public Result removeRole(Long uid, String roleName) { @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getUsersByRole(String role) { - List users = Ebean.find(User.class).where().eq("roles.name", role).orderBy("lastName").findList(); - ArrayNode array = Json.newArray(); - array.addAll( - users - .stream() - .map(u -> { - ObjectNode part = Json.newObject(); - part.put("id", u.getId()); - part.put("name", String.format("%s %s", u.getFirstName(), u.getLastName())); - return part; - }) - .collect(Collectors.toList()) - ); - return ok(Json.toJson(array)); + PathProperties pp = PathProperties.parse("(*, roles(*), permissions(*))"); + List users = DB.find(User.class).where().eq("roles.name", role).orderBy("lastName").findList(); + return ok(users, pp); } private static ArrayNode asArray(List users) { @@ -189,13 +177,13 @@ private static ArrayNode asArray(List users) { part.put("email", u.getEmail()); return part; }) - .collect(Collectors.toList()) + .toList() ); return array; } private List findUsersByRoleAndName(String role, String nameFilter) { - ExpressionList el = Ebean.find(User.class).where().eq("roles.name", role).disjunction(); + ExpressionList el = DB.find(User.class).where().eq("roles.name", role).disjunction(); el = applyUserFilter(null, el, nameFilter); return el.endJunction().findList(); } @@ -212,7 +200,7 @@ public Result getQuestionOwnersByRoleFilter( Set owners = new HashSet<>(); owners.add(request.attrs().get(Attrs.AUTHENTICATED_USER)); if (qid.isPresent()) { - Question question = Ebean.find(Question.class, qid.get()); + Question question = DB.find(Question.class, qid.get()); if (question == null) { return notFound(); } @@ -224,17 +212,17 @@ public Result getQuestionOwnersByRoleFilter( @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getExamInspectorsByRoleFilter(String role, Long eid, String criteria) { - List inspections = Ebean.find(ExamInspection.class).where().eq("exam.id", eid).findList(); + List inspections = DB.find(ExamInspection.class).where().eq("exam.id", eid).findList(); List users = findUsersByRoleAndName(role, criteria); - users.removeAll(inspections.stream().map((ExamInspection::getUser)).collect(Collectors.toList())); + users.removeAll(inspections.stream().map((ExamInspection::getUser)).toList()); return ok(Json.toJson(asArray(users))); } @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public Result getUnenrolledStudents(Long eid, String criteria) { - List enrolments = Ebean.find(ExamEnrolment.class).where().eq("exam.id", eid).findList(); + List enrolments = DB.find(ExamEnrolment.class).where().eq("exam.id", eid).findList(); List users = findUsersByRoleAndName("STUDENT", criteria); - users.removeAll(enrolments.stream().map((ExamEnrolment::getUser)).collect(Collectors.toList())); + users.removeAll(enrolments.stream().map((ExamEnrolment::getUser)).toList()); return ok(Json.toJson(asArray(users))); } @@ -242,7 +230,7 @@ public Result getUnenrolledStudents(Long eid, String criteria) { @Restrict({ @Group("STUDENT") }) public Result updateUserAgreementAccepted(Http.Request request) { Result result; - User user = Ebean + User user = DB .find(User.class) .fetch("roles", "name") .fetch("language") @@ -266,7 +254,7 @@ public Result updateUserAgreementAccepted(Http.Request request) { public Result updateLanguage(Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); String lang = request.attrs().get(Attrs.LANG); - Language language = Ebean.find(Language.class, lang); + Language language = DB.find(Language.class, lang); if (language == null) { return badRequest("Unsupported language code"); } diff --git a/app/controllers/assets/FrontendController.scala b/app/controllers/assets/FrontendController.scala index 5eed918bb9..2bef290c4c 100644 --- a/app/controllers/assets/FrontendController.scala +++ b/app/controllers/assets/FrontendController.scala @@ -6,12 +6,9 @@ import play.api.mvc._ import javax.inject._ @Singleton -class FrontendController @Inject()(assets: Assets, cc: ControllerComponents) - extends AbstractController(cc) { +class FrontendController @Inject() (assets: Assets, cc: ControllerComponents) extends AbstractController(cc): def index: Action[AnyContent] = assets.at("index.html") def assetOrDefault(resource: String): Action[AnyContent] = - if (resource.contains(".")) assets.at(resource) else index - -} + if resource.contains(".") then assets.at(resource) else index diff --git a/app/controllers/base/BaseController.java b/app/controllers/base/BaseController.java index cbd0afbdff..3d206515cf 100644 --- a/app/controllers/base/BaseController.java +++ b/app/controllers/base/BaseController.java @@ -18,28 +18,23 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; -import exceptions.MalformedDataException; import impl.NoShowHandler; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.text.PathProperties; import java.io.IOException; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import java.util.stream.Collectors; import models.Exam; import models.ExamEnrolment; import models.Role; import models.User; -import play.Logger; -import play.data.Form; import play.data.FormFactory; -import play.libs.concurrent.HttpExecutionContext; +import play.libs.concurrent.ClassLoaderExecutionContext; import play.libs.typedmap.TypedKey; import play.mvc.Controller; import play.mvc.Http; @@ -49,55 +44,45 @@ public class BaseController extends Controller { - private static final Logger.ALogger logger = Logger.of(BaseController.class); - @Inject protected FormFactory formFactory; @Inject - protected HttpExecutionContext ec; + protected ClassLoaderExecutionContext ec; @Inject - private NoShowHandler noShowHandler; - - protected T bindForm(final Class clazz, Http.Request request) { - final Form form = formFactory.form(clazz); - if (form.hasErrors()) { - throw new MalformedDataException(form.errorsAsJson().asText()); - } - return form.bindFromRequest(request).get(); - } + protected NoShowHandler noShowHandler; protected Result ok(Object object) { - String body = Ebean.json().toJson(object); + var body = DB.json().toJson(object); return ok(body).as("application/json"); } protected Result ok(Object object, PathProperties props) { - String body = Ebean.json().toJson(object, props); + var body = DB.json().toJson(object, props); return ok(body).as("application/json"); } protected Result created(Object object) { - String body = Ebean.json().toJson(object); + var body = DB.json().toJson(object); return created(body).as("application/json"); } protected Result created(Object object, PathProperties props) { - String body = Ebean.json().toJson(object, props); + var body = DB.json().toJson(object, props); return created(body).as("application/json"); } protected ExpressionList applyUserFilter(String prefix, ExpressionList query, String filter) { - ExpressionList result = query; - String rawFilter = filter.replaceAll(" +", " ").trim(); - String condition = String.format("%%%s%%", rawFilter); - String fnField = prefix == null ? "firstName" : String.format("%s.firstName", prefix); - String lnField = prefix == null ? "lastName" : String.format("%s.lastName", prefix); + var result = query; + var rawFilter = filter.replaceAll(" +", " ").trim(); + var condition = String.format("%%%s%%", rawFilter); + var fnField = prefix == null ? "firstName" : String.format("%s.firstName", prefix); + var lnField = prefix == null ? "lastName" : String.format("%s.lastName", prefix); if (rawFilter.contains(" ")) { // Possible that user provided us two names. Let's try out some combinations of first and last names - String name1 = rawFilter.split(" ")[0]; - String name2 = rawFilter.split(" ")[1]; + var name1 = rawFilter.split(" ")[0]; + var name2 = rawFilter.split(" ")[1]; result = result .or() @@ -117,7 +102,7 @@ protected ExpressionList applyUserFilter(String prefix, ExpressionList } private void handleNoShow(User user, Long examId) { - List enrolments = Ebean + var enrolments = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("exam") @@ -128,8 +113,8 @@ private void handleNoShow(User user, Long examId) { .lt("reservation.endAt", new Date()) .lt("examinationEventConfiguration.examinationEvent.start", new Date()) // FIXME: exam period .endOr() - // Either a) exam id matches and exam state is published OR - // b) collaborative exam id matches and exam is NULL + // Either (a) exam id matches and exam state is published OR + // (b) collaborative exam id matches and exam is NULL .or() .and() .eq("exam.id", examId) @@ -151,7 +136,7 @@ protected boolean isAllowedToParticipate(Exam exam, User user) { if (trialCount == null) { return true; } - List trials = Ebean + var trials = DB .find(ExamEnrolment.class) .fetch("exam") .where() @@ -163,7 +148,7 @@ protected boolean isAllowedToParticipate(Exam exam, User user) { .findList() .stream() .sorted(Comparator.comparing(ExamEnrolment::getId).reversed()) - .collect(Collectors.toList()); + .toList(); if (trials.size() >= trialCount) { return trials.stream().limit(trialCount).anyMatch(ExamEnrolment::isProcessed); @@ -183,12 +168,12 @@ protected Result writeAnonymousResult(Http.Request request, Result result, boole } protected Result writeAnonymousResult(Http.Request request, Result result, boolean anonymous) { - User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + var user = request.attrs().get(Attrs.AUTHENTICATED_USER); return writeAnonymousResult(request, result, anonymous, user.hasRole(Role.Name.ADMIN)); } protected Result writeAnonymousResult(Http.Request request, Result result, Set anonIds) { - User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + var user = request.attrs().get(Attrs.AUTHENTICATED_USER); if (!anonIds.isEmpty() && !user.hasRole(Role.Name.ADMIN)) { return withAnonymousHeader(result, request, anonIds); } @@ -202,23 +187,21 @@ private Result withAnonymousHeader(Result result, Http.Request request, Set id = SanitizingHelper.parse("id", node, Long.class); + if (id.isEmpty()) { + return; + } + MultipleChoiceOption option = DB.find(MultipleChoiceOption.class, id.get()); if (option != null) { option.setOption(SanitizingHelper.parse("option", node, String.class).orElse(null)); option.setClaimChoiceType( diff --git a/app/controllers/integration/ExamAPIController.java b/app/controllers/integration/ExamAPIController.java index 19a242b071..07e3fbbef5 100644 --- a/app/controllers/integration/ExamAPIController.java +++ b/app/controllers/integration/ExamAPIController.java @@ -17,7 +17,7 @@ import be.objectify.deadbolt.java.actions.SubjectNotPresent; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Query; import io.ebean.text.PathProperties; import java.util.List; @@ -35,7 +35,7 @@ public Result getActiveExams(Optional date) { PathProperties pp = PathProperties.parse( "(course(name, code, credits, " + "gradeScale(description, externalRef, displayName), organisation(code, name, nameAbbreviation)) " + - "id, name, examActiveStartDate, examActiveEndDate, duration, enrollInstruction, " + + "id, name, periodStart, periodEnd, duration, enrollInstruction, " + "examLanguages(code, name), gradeScale(description, externalRef, displayName), " + "examOwners(firstName, lastName, email), examType(type)" + ")" @@ -43,12 +43,12 @@ public Result getActiveExams(Optional date) { DateTime dateTime = date.isPresent() ? ISODateTimeFormat.dateTimeParser().parseDateTime(date.get()) : DateTime.now(); - Query query = Ebean.find(Exam.class); + Query query = DB.find(Exam.class); query.apply(pp); List exams = query .where() .eq("state", Exam.State.PUBLISHED) - .ge("examActiveEndDate", dateTime) + .ge("periodEnd", dateTime) .eq("executionType.type", ExamExecutionType.Type.PUBLIC.toString()) .findList(); diff --git a/app/controllers/integration/ExamRecordAPIController.java b/app/controllers/integration/ExamRecordAPIController.java index a1a7f13173..fd2f4306b4 100644 --- a/app/controllers/integration/ExamRecordAPIController.java +++ b/app/controllers/integration/ExamRecordAPIController.java @@ -17,9 +17,8 @@ import be.objectify.deadbolt.java.actions.SubjectNotPresent; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.List; -import java.util.stream.Collectors; import models.ExamRecord; import models.dto.ExamScore; import org.joda.time.DateTime; @@ -34,14 +33,16 @@ public Result getNewRecords(String startDate) { return ok(Json.toJson(getScores(startDate))); } - private static List getScores(String startDate) { + private List getScores(String startDate) { DateTime start = ISODateTimeFormat.dateTimeParser().parseDateTime(startDate); - List examRecords = Ebean + return DB .find(ExamRecord.class) .fetch("examScore") .where() - .gt("timeStamp", start.toDate()) - .findList(); - return examRecords.stream().map(ExamRecord::getExamScore).collect(Collectors.toList()); + .gt("timeStamp", start) + .findList() + .stream() + .map(ExamRecord::getExamScore) + .toList(); } } diff --git a/app/controllers/integration/ReportAPIController.java b/app/controllers/integration/ReportAPIController.java index d63bfa9d74..b7d8533f0f 100644 --- a/app/controllers/integration/ReportAPIController.java +++ b/app/controllers/integration/ReportAPIController.java @@ -2,7 +2,7 @@ import be.objectify.deadbolt.java.actions.SubjectNotPresent; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.Query; import io.ebean.text.PathProperties; @@ -29,11 +29,11 @@ public Result getExamEnrolments(Optional start, Optional end) { "user(id, firstName, lastName, eppn, email, userIdentifier), " + "exam(id, name, course(name, code, credits, " + "gradeScale(description, displayName), organisation(code, name)), softwares(name), duration, examTypeId, executionTypeId, " + - "trialCount, answerLanguage, instruction, examActiveStartDate, examActiveEndDate)" + + "trialCount, answerLanguage, instruction, periodStart, periodEnd)" + ")" ); - Query query = Ebean.find(ExamEnrolment.class); + Query query = DB.find(ExamEnrolment.class); pp.apply(query); ExpressionList el = query @@ -61,7 +61,7 @@ public Result getExamEnrolments(Optional start, Optional end) { .map(participation -> participation.getExam().getParent().getId()) .collect(Collectors.toSet()); - Map> softwaresByExam = Ebean + Map> softwaresByExam = DB .find(Exam.class) .fetch("softwares", "name") .where() @@ -81,7 +81,7 @@ public Result getExamEnrolments(Optional start, Optional end) { .forEach(participation -> { Long parentId = participation.getExam().getParent().getId(); List softwares = softwaresByExam.get(parentId); - if (softwares != null || !softwares.isEmpty()) { + if (softwares != null && !softwares.isEmpty()) { participation.getExam().setSoftwareInfo(softwares); } }); diff --git a/app/controllers/integration/ReservationAPIController.java b/app/controllers/integration/ReservationAPIController.java index 46311f6f96..22f24e291d 100644 --- a/app/controllers/integration/ReservationAPIController.java +++ b/app/controllers/integration/ReservationAPIController.java @@ -17,14 +17,13 @@ import be.objectify.deadbolt.java.actions.SubjectNotPresent; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import io.ebean.Query; import io.ebean.text.PathProperties; import java.util.Comparator; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import javax.inject.Inject; import models.Exam; import models.ExamRoom; @@ -56,7 +55,7 @@ public Result getReservations(Optional start, Optional end, Opti "), " + "machine(name, ipAddress, otherIdentifier, room(name, roomCode)))" ); - Query query = Ebean.find(Reservation.class); + Query query = DB.find(Reservation.class); pp.apply(query); ExpressionList el = query .where() @@ -91,7 +90,7 @@ public Result getReservations(Optional start, Optional end, Opti r.setEndAt(dateTimeHandler.normalize(r.getEndAt(), r)); }) .sorted(Comparator.comparing(Reservation::getStartAt)) - .collect(Collectors.toList()); + .toList(); return ok(reservations, pp); } @@ -99,7 +98,7 @@ public Result getReservations(Optional start, Optional end, Opti @SubjectNotPresent public Result getRooms() { PathProperties pp = PathProperties.parse("(*, defaultWorkingHours(*), mailAddress(*), examMachines(*))"); - Query query = Ebean.find(ExamRoom.class); + Query query = DB.find(ExamRoom.class); pp.apply(query); List rooms = query.orderBy("name").findList(); return ok(rooms, pp); @@ -112,7 +111,7 @@ public Result getRoomOpeningHours(Long roomId, Optional date) { } LocalDate searchDate = ISODateTimeFormat.dateParser().parseLocalDate(date.get()); PathProperties pp = PathProperties.parse("(*, defaultWorkingHours(*), calendarExceptionEvents(*))"); - Query query = Ebean.find(ExamRoom.class); + Query query = DB.find(ExamRoom.class); pp.apply(query); ExamRoom room = query.where().idEq(roomId).findOne(); if (room == null) { @@ -127,7 +126,7 @@ public Result getRoomOpeningHours(Long roomId, Optional date) { LocalDate end = new LocalDate(ee.getEndDate()).dayOfMonth().withMaximumValue(); return !start.isAfter(searchDate) && !end.isBefore(searchDate); }) - .collect(Collectors.toList()) + .toList() ); return ok(room, pp); } diff --git a/app/controllers/iop/collaboration/api/CollaborativeAttachmentInterface.java b/app/controllers/iop/collaboration/api/CollaborativeAttachmentInterface.java index e99a9e33f9..0d4324f748 100644 --- a/app/controllers/iop/collaboration/api/CollaborativeAttachmentInterface.java +++ b/app/controllers/iop/collaboration/api/CollaborativeAttachmentInterface.java @@ -19,19 +19,16 @@ import static play.mvc.Http.Status.NOT_FOUND; import static play.mvc.Http.Status.OK; -import akka.stream.IOResult; -import akka.stream.javadsl.FileIO; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Pattern; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import controllers.BaseAttachmentInterface; -import io.ebean.Ebean; +import io.ebean.DB; import io.vavr.control.Either; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.Set; @@ -47,6 +44,10 @@ import models.questions.EssayAnswer; import models.sections.ExamSectionQuestion; import org.apache.commons.lang3.StringUtils; +import org.apache.pekko.stream.IOResult; +import org.apache.pekko.stream.javadsl.FileIO; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; import play.libs.Files; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; @@ -101,12 +102,8 @@ default Either, LanguageInspection> findLanguageInspecti Http.MultipartFormData.FilePart file ) { Source> source = FileIO.fromPath(file.getRef().path()); - Http.MultipartFormData.FilePart>> filePart = new Http.MultipartFormData.FilePart<>( - "file", - file.getFilename(), - file.getContentType(), - source - ); + Http.MultipartFormData.FilePart>> filePart = + new Http.MultipartFormData.FilePart<>("file", file.getFilename(), file.getContentType(), source); return Source.from(Set.of(filePart)); } @@ -422,9 +419,9 @@ default Optional parseUrl(String url, String id) { String id2 = id == null ? "" : id; urlString = String.format(urlString, id2); try { - return Optional.of(new URL(urlString)); + return Optional.of(URI.create(urlString).toURL()); } catch (MalformedURLException e) { - logger().error("Malformed URL {}", e); + logger().error("Malformed URL", e); return Optional.empty(); } } @@ -478,7 +475,7 @@ default CompletionStage createExternalAttachment( a.setFileName(json.get("displayName").asText()); container.setAttachment(a); if (setExam(externalExam, exam, user)) { - final String body = Ebean.json().toJson(a); + final String body = DB.json().toJson(a); return CompletableFuture.completedFuture(Results.created(body).as("application/json")); } return CompletableFuture.completedFuture(Results.internalServerError()); diff --git a/app/controllers/iop/collaboration/impl/CollaborationController.java b/app/controllers/iop/collaboration/impl/CollaborationController.java index 68e46a2c2f..6a71f1bf64 100644 --- a/app/controllers/iop/collaboration/impl/CollaborationController.java +++ b/app/controllers/iop/collaboration/impl/CollaborationController.java @@ -6,15 +6,13 @@ import controllers.base.BaseController; import controllers.iop.collaboration.api.CollaborativeExamLoader; import impl.ExamUpdater; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Model; import io.ebean.text.PathProperties; import io.vavr.control.Either; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Map; import java.util.Optional; @@ -31,9 +29,11 @@ import models.User; import models.json.CollaborativeExam; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.Json; import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; import play.mvc.Result; import util.config.ConfigReader; @@ -55,34 +55,32 @@ public class CollaborationController extends BaseController { @Inject protected ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(CollaborationController.class); + private final Logger logger = LoggerFactory.getLogger(CollaborationController.class); Optional parseUrl() { String url = String.format("%s/api/exams", configReader.getIopHost()); try { - return Optional.of(new URL(url)); + return Optional.of(URI.create(url).toURL()); } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); + logger.error("Malformed URL", e); return Optional.empty(); } } - Optional parseUrlWithSearchParam(String filter, boolean anonymous) { - try { - if (filter == null) { - return Optional.empty(); - } - String paramStr = String.format( - "filter=%s&anonymous=%s", - URLEncoder.encode(filter, StandardCharsets.UTF_8), - anonymous - ); - URI uri = URI.create(String.format("%s/api/exams/search?%s", configReader.getIopHost(), paramStr)); - return Optional.of(uri.toURL()); - } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); - return Optional.empty(); - } + WSRequest getSearchRequest(Optional filter) { + String host = configReader.getIopHost(); + return filter + .map(s -> { + URI uri = URI.create(String.format("%s/api/exams/search", host)); + return wsClient + .url(uri.toString()) + .addQueryParameter("filter", s) + .addQueryParameter("anonymous", "false"); + }) + .orElseGet(() -> { + URI uri = URI.create(String.format("%s/api/exams", host)); + return wsClient.url(uri.toString()); + }); } protected CompletionStage> downloadExam(CollaborativeExam ce) { @@ -103,6 +101,7 @@ protected void cleanUser(User user) { user.getEnrolments().clear(); user.getParticipations().clear(); user.getInspections().clear(); + user.getPermissions().clear(); } void updateLocalReferences(JsonNode root, Map locals) { @@ -141,30 +140,26 @@ boolean isAuthorizedToView(Exam exam, User user, String homeOrg) { } return ( user.getLoginRole() == Role.Name.ADMIN || - ( - exam + (exam .getExamOwners() .stream() .anyMatch(u -> u.getEmail().equalsIgnoreCase(user.getEmail()) || u.getEmail().equalsIgnoreCase(user.getEppn()) ) && - exam.hasState(Exam.State.PRE_PUBLISHED, Exam.State.PUBLISHED) - ) + exam.hasState(Exam.State.PRE_PUBLISHED, Exam.State.PUBLISHED)) ); } boolean isUnauthorizedToAssess(Exam exam, User user) { return ( user.getLoginRole() != Role.Name.ADMIN && - ( - exam + (exam .getExamOwners() .stream() .noneMatch(u -> u.getEmail().equalsIgnoreCase(user.getEmail()) || u.getEmail().equalsIgnoreCase(user.getEppn()) ) || - !exam.hasState(Exam.State.REVIEW, Exam.State.REVIEW_STARTED, Exam.State.GRADED) - ) + !exam.hasState(Exam.State.REVIEW, Exam.State.REVIEW_STARTED, Exam.State.GRADED)) ); } @@ -200,7 +195,7 @@ Either> findExamsToProcess(WSResponse r return Either.left(internalServerError(root.get("message").asText("Connection refused"))); } - Map locals = Ebean + Map locals = DB .find(CollaborativeExam.class) .findSet() .stream() @@ -216,22 +211,22 @@ Either> findExamsToProcess(WSResponse r } Either, CollaborativeExam> findCollaborativeExam(Long id) { - return Ebean + return DB .find(CollaborativeExam.class) .where() .idEq(id) .findOneOrEmpty() ., CollaborativeExam>>map(Either::right) - .orElse(Either.left(wrapAsPromise(notFound("sitnet_error_exam_not_found")))); + .orElse(Either.left(wrapAsPromise(notFound("i18n_error_exam_not_found")))); } Either, CollaborativeExam> findCollaborativeExam(String ref) { - return Ebean + return DB .find(CollaborativeExam.class) .where() .eq("externalRef", ref) .findOneOrEmpty() ., CollaborativeExam>>map(Either::right) - .orElse(Either.left(wrapAsPromise(notFound("sitnet_error_exam_not_found")))); + .orElse(Either.left(wrapAsPromise(notFound("i18n_error_exam_not_found")))); } } diff --git a/app/controllers/iop/collaboration/impl/CollaborativeAttachmentController.java b/app/controllers/iop/collaboration/impl/CollaborativeAttachmentController.java index 5d3d5a688c..66759d6115 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeAttachmentController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeAttachmentController.java @@ -16,12 +16,10 @@ package controllers.iop.collaboration.impl; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.iop.collaboration.api.CollaborativeAttachmentInterface; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import java.net.URL; import java.util.Optional; @@ -33,6 +31,8 @@ import models.Exam; import models.User; import models.json.CollaborativeExam; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; import play.libs.Files; import play.libs.Json; import play.libs.ws.WSClient; @@ -50,12 +50,9 @@ public class CollaborativeAttachmentController @Inject private WSClient wsClient; - @Inject - private ConfigReader configReader; - @Override public Optional getExternalExam(Long eid, Http.Request request) { - final ExpressionList query = Ebean.find(CollaborativeExam.class).where().eq("id", eid); + final ExpressionList query = DB.find(CollaborativeExam.class).where().eq("id", eid); return query.findOneOrEmpty(); } diff --git a/app/controllers/iop/collaboration/impl/CollaborativeCalendarController.java b/app/controllers/iop/collaboration/impl/CollaborativeCalendarController.java index 6e013ba1a2..6f81f98104 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeCalendarController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeCalendarController.java @@ -1,11 +1,11 @@ package controllers.iop.collaboration.impl; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import impl.CalendarHandler; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; +import io.ebean.Transaction; import io.ebean.text.PathProperties; import java.util.Collection; import java.util.Collections; @@ -23,8 +23,10 @@ import models.User; import models.json.CollaborativeExam; import models.sections.ExamSection; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; @@ -48,19 +50,19 @@ public class CollaborativeCalendarController extends CollaborationController { @Inject DateTimeHandler dateTimeHandler; - private static final Logger.ALogger logger = Logger.of(CollaborativeCalendarController.class); + private final Logger logger = LoggerFactory.getLogger(CollaborativeCalendarController.class); @Restrict({ @Group("STUDENT") }) public CompletionStage getExamInfo(Long id) { - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, id); + CollaborativeExam ce = DB.find(CollaborativeExam.class, id); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } return downloadExam(ce) .thenApplyAsync(result -> { if (result.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = result.get(); return ok(exam, PathProperties.parse("(*, examSections(*, examMaterials(*)), examLanguages(*))")); @@ -74,13 +76,13 @@ protected Optional checkEnrolment(ExamEnrolment enrolment, Exam exam, Us exam.getState() == Exam.State.STUDENT_STARTED || (oldReservation != null && oldReservation.toInterval().isBefore(DateTime.now())) ) { - return Optional.of(forbidden("sitnet_reservation_in_effect")); + return Optional.of(forbidden("i18n_reservation_in_effect")); } // No previous reservation or it's in the future // If no previous reservation, check if allowed to participate. This check is skipped if user already // has a reservation to this exam so that change of reservation is always possible. if (oldReservation == null && !isAllowedToParticipate(exam, user)) { - return Optional.of(forbidden("sitnet_no_trials_left")); + return Optional.of(forbidden("i18n_no_trials_left")); } return Optional.empty(); } @@ -93,19 +95,19 @@ public CompletionStage createReservation(Http.Request request) { Long examId = request.attrs().get(Attrs.EXAM_ID); DateTime start = request.attrs().get(Attrs.START_DATE); DateTime end = request.attrs().get(Attrs.END_DATE); - Collection aids = request.attrs().get(Attrs.ACCESSABILITES); + Collection aids = request.attrs().get(Attrs.ACCESSIBILITIES); Collection sectionIds = request.attrs().get(Attrs.SECTION_IDS); - ExamRoom room = Ebean.find(ExamRoom.class, roomId); + ExamRoom room = DB.find(ExamRoom.class, roomId); DateTime now = dateTimeHandler.adjustDST(DateTime.now(), room); final User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, examId); + CollaborativeExam ce = DB.find(CollaborativeExam.class, examId); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } - final ExamEnrolment enrolment = Ebean + final ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .where() @@ -117,13 +119,13 @@ public CompletionStage createReservation(Http.Request request) { .endJunction() .findOne(); if (enrolment == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } return downloadExam(ce) .thenApplyAsync(result -> { if (result.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = result.get(); Optional badEnrolment = checkEnrolment(enrolment, exam, user); @@ -132,14 +134,13 @@ public CompletionStage createReservation(Http.Request request) { } Optional machine = calendarHandler.getRandomMachine(room, exam, start, end, aids); if (machine.isEmpty()) { - return forbidden("sitnet_no_machines_available"); + return forbidden("i18n_no_machines_available"); } // We are good to go :) // Start manual transaction. - Ebean.beginTransaction(); - try { + try (Transaction tx = DB.beginTransaction()) { // Take pessimistic lock for user to prevent multiple reservations creating. - Ebean.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); + DB.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); Reservation oldReservation = enrolment.getReservation(); Reservation reservation = calendarHandler.createReservation(start, end, machine.get(), user); // Nuke the old reservation if any @@ -149,11 +150,8 @@ public CompletionStage createReservation(Http.Request request) { oldReservation.delete(); } Result newReservation = makeNewReservation(enrolment, exam, reservation, user, sectionIds); - Ebean.commitTransaction(); + tx.commit(); return newReservation; - } finally { - // End transaction to release lock. - Ebean.endTransaction(); } }); } @@ -170,7 +168,7 @@ private Result makeNewReservation( enrolment.setReservationCanceled(false); Set sections = sectionIds.isEmpty() ? Collections.emptySet() - : Ebean.find(ExamSection.class).where().idIn(sectionIds).findSet(); + : DB.find(ExamSection.class).where().idIn(sectionIds).findSet(); enrolment.setOptionalSections(sections); enrolment.save(); // Send some emails asynchronously @@ -198,22 +196,22 @@ public CompletionStage getSlots( Http.Request request ) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, examId); + CollaborativeExam ce = DB.find(CollaborativeExam.class, examId); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } ExamEnrolment enrolment = getEnrolledExam(examId, user); if (enrolment == null) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_not_found")); + return wrapAsPromise(forbidden("i18n_error_enrolment_not_found")); } return downloadExam(ce) .thenApplyAsync(result -> { if (result.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = result.get(); if (!exam.hasState(Exam.State.PUBLISHED)) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } List accessibilityIds = aids.orElse(Collections.emptyList()); return calendarHandler.getSlots(user, exam, roomId, day, accessibilityIds); @@ -222,7 +220,7 @@ public CompletionStage getSlots( private ExamEnrolment getEnrolledExam(Long examId, User user) { DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - return Ebean + return DB .find(ExamEnrolment.class) .where() .eq("user", user) diff --git a/app/controllers/iop/collaboration/impl/CollaborativeEnrolmentController.java b/app/controllers/iop/collaboration/impl/CollaborativeEnrolmentController.java index 4b9298b144..d4810c800f 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeEnrolmentController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeEnrolmentController.java @@ -2,16 +2,15 @@ import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; -import io.ebean.Ebean; +import io.ebean.DB; +import io.ebean.Transaction; import io.ebean.text.PathProperties; import io.vavr.control.Either; -import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionStage; import java.util.function.Function; -import java.util.stream.Collectors; import javax.inject.Inject; import models.Exam; import models.ExamEnrolment; @@ -19,7 +18,8 @@ import models.User; import models.json.CollaborativeExam; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; import play.mvc.Http; @@ -37,7 +37,7 @@ public CollaborativeEnrolmentController(DateTimeHandler dateTimeHandler) { this.dateTimeHandler = dateTimeHandler; } - private static final Logger.ALogger logger = Logger.of(CollaborativeEnrolmentController.class); + private final Logger logger = LoggerFactory.getLogger(CollaborativeEnrolmentController.class); private boolean isEnrollable(Exam exam, String homeOrg) { if (exam.getOrganisations() != null) { @@ -49,29 +49,25 @@ private boolean isEnrollable(Exam exam, String homeOrg) { return ( exam.getState() == Exam.State.PUBLISHED && exam.getExecutionType().getType().equals(ExamExecutionType.Type.PUBLIC.toString()) && - exam.getExamActiveEndDate().isAfterNow() + exam.getPeriodEnd() != null && + exam.getPeriodEnd().isAfterNow() ); } private Either checkExam(Exam exam, User user) { String homeOrg = configReader.getHomeOrganisationRef(); if (exam == null || !isEnrollable(exam, homeOrg)) { - return Either.left(notFound("sitnet_error_exam_not_found")); + return Either.left(notFound("i18n_error_exam_not_found")); } if (!isAllowedToParticipate(exam, user)) { - return Either.left(forbidden("sitnet_no_trials_left")); + return Either.left(forbidden("i18n_no_trials_left")); } return Either.right(exam); } @Restrict({ @Group("STUDENT") }) public CompletionStage searchExams(Optional filter) { - Optional url = filter.orElse("").isEmpty() ? parseUrl() : parseUrlWithSearchParam(filter.get(), false); - if (url.isEmpty()) { - return wrapAsPromise(internalServerError("sitnet_internal_error")); - } - - WSRequest request = wsClient.url(url.get().toString()); + WSRequest request = getSearchRequest(filter); String homeOrg = configReader.getHomeOrganisationRef(); Function onSuccess = response -> findExamsToProcess(response) @@ -81,13 +77,13 @@ public CompletionStage searchExams(Optional filter) { .stream() .map(e -> e.getKey().getExam(e.getValue())) .filter(e -> isEnrollable(e, homeOrg)) - .collect(Collectors.toList()); + .toList(); return ok( exams, PathProperties.parse( "(examOwners(firstName, lastName), examInspections(user(firstName, lastName))" + - "examLanguages(code, name), id, name, examActiveStartDate, examActiveEndDate, " + + "examLanguages(code, name), id, name, periodStart, periodEnd, " + "enrollInstruction, implementation, examinationEventConfigurations)" ) ); @@ -99,9 +95,9 @@ public CompletionStage searchExams(Optional filter) { @Authenticated @Restrict({ @Group("STUDENT") }) public CompletionStage checkIfEnrolled(Long id, Http.Request request) { - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, id); + CollaborativeExam ce = DB.find(CollaborativeExam.class, id); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); return downloadExam(ce) @@ -109,7 +105,7 @@ public CompletionStage checkIfEnrolled(Long id, Http.Request request) { checkExam(result.orElse(null), user) .map(e -> { DateTime now = dateTimeHandler.adjustDST(new DateTime()); - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .where() .eq("user", user) @@ -134,6 +130,7 @@ private static ExamEnrolment makeEnrolment(CollaborativeExam exam, User user) { enrolment.setEnrolledOn(DateTime.now()); enrolment.setUser(user); enrolment.setCollaborativeExam(exam); + enrolment.setRandomDelay(); enrolment.save(); return enrolment; } @@ -143,10 +140,10 @@ private Optional handleFutureReservations(List enrolments List enrolmentsWithFutureReservations = enrolments .stream() .filter(ee -> ee.getReservation().toInterval().isAfter(now)) - .collect(Collectors.toList()); + .toList(); if (enrolmentsWithFutureReservations.size() > 1) { logger.error( - "Several enrolments with future reservations found for user {} and collab exam {}", + "Several enrolments with future reservations found for user {} and collaborative exam {}", user, ce.getId() ); @@ -154,7 +151,7 @@ private Optional handleFutureReservations(List enrolments } // reservation in the future, replace it if (!enrolmentsWithFutureReservations.isEmpty()) { - enrolmentsWithFutureReservations.get(0).delete(); + enrolmentsWithFutureReservations.getFirst().delete(); ExamEnrolment newEnrolment = makeEnrolment(ce, user); return Optional.of(ok(newEnrolment)); } @@ -163,12 +160,11 @@ private Optional handleFutureReservations(List enrolments private Result doCreateEnrolment(CollaborativeExam ce, User user) { // Begin manual transaction - Ebean.beginTransaction(); - try { + try (Transaction tx = DB.beginTransaction()) { // Take pessimistic lock for user to prevent multiple enrolments creating. - Ebean.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); + DB.find(User.class).forUpdate().where().eq("id", user.getId()).findOne(); - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .fetch("reservation") .where() @@ -177,7 +173,7 @@ private Result doCreateEnrolment(CollaborativeExam ce, User user) { .findList(); // already enrolled if (enrolments.stream().anyMatch(e -> e.getReservation() == null)) { - return forbidden("sitnet_error_enrolment_exists"); + return forbidden("i18n_error_enrolment_exists"); } // reservation in effect if ( @@ -186,37 +182,34 @@ private Result doCreateEnrolment(CollaborativeExam ce, User user) { .map(ExamEnrolment::getReservation) .anyMatch(r -> r.toInterval().contains(dateTimeHandler.adjustDST(DateTime.now(), r))) ) { - return forbidden("sitnet_reservation_in_effect"); + return forbidden("i18n_reservation_in_effect"); } return handleFutureReservations(enrolments, user, ce) .orElseGet(() -> { ExamEnrolment newEnrolment = makeEnrolment(ce, user); - Ebean.commitTransaction(); + tx.commit(); return ok(newEnrolment); }); - } finally { - // End transaction to release lock. - Ebean.endTransaction(); } } @Authenticated @Restrict({ @Group("ADMIN"), @Group("STUDENT") }) public CompletionStage createEnrolment(Long id, Http.Request request) { - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, id); + CollaborativeExam ce = DB.find(CollaborativeExam.class, id); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } User user = request.attrs().get(Attrs.AUTHENTICATED_USER); return downloadExam(ce) .thenApplyAsync(result -> { if (result.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = result.get(); String homeOrg = configReader.getHomeOrganisationRef(); if (!isEnrollable(exam, homeOrg)) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } if (isAllowedToParticipate(exam, user)) { return doCreateEnrolment(ce, user); diff --git a/app/controllers/iop/collaboration/impl/CollaborativeExamController.java b/app/controllers/iop/collaboration/impl/CollaborativeExamController.java index 21e6a8ba56..6e198d63f6 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeExamController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeExamController.java @@ -15,12 +15,11 @@ package controllers.iop.collaboration.impl; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import java.net.URL; import java.util.List; import java.util.Optional; @@ -40,6 +39,7 @@ import models.User; import models.json.CollaborativeExam; import models.sections.ExamSection; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import play.libs.Json; import play.libs.ws.WSRequest; @@ -52,13 +52,9 @@ import sanitizers.ExamUpdateSanitizer; import scala.concurrent.duration.Duration; import security.Authenticated; -import util.config.ConfigReader; public class CollaborativeExamController extends CollaborationController { - @Inject - private ConfigReader configReader; - @Inject private ActorSystem as; @@ -66,7 +62,7 @@ public class CollaborativeExamController extends CollaborationController { private EmailComposer composer; private Exam prepareDraft(User user) { - ExamExecutionType examExecutionType = Ebean + ExamExecutionType examExecutionType = DB .find(ExamExecutionType.class) .where() .eq("type", ExamExecutionType.Type.PUBLIC.toString()) @@ -87,17 +83,16 @@ private Exam prepareDraft(User user) { examSection.setSequenceNumber(0); exam.getExamSections().add(examSection); - exam.getExamLanguages().add(Ebean.find(Language.class, "fi")); - exam.setExamType(Ebean.find(ExamType.class, 2)); // Final + exam.getExamLanguages().add(DB.find(Language.class, "fi")); + exam.setExamType(DB.find(ExamType.class, 2)); // Final DateTime start = DateTime.now().withTimeAtStartOfDay(); - exam.setExamActiveStartDate(start); - exam.setExamActiveEndDate(start.plusDays(1)); - exam.setDuration(configReader.getExamDurations().get(0)); // check - exam.setGradeScale(Ebean.find(GradeScale.class).findList().get(0)); // check + exam.setPeriodStart(start); + exam.setPeriodEnd(start.plusDays(1)); + exam.setDuration(configReader.getExamDurations().getFirst()); // check + exam.setGradeScale(DB.find(GradeScale.class).findList().getFirst()); // check exam.setTrialCount(1); - exam.setExpanded(true); exam.setAnonymous(true); return exam; @@ -105,14 +100,9 @@ private Exam prepareDraft(User user) { @Authenticated @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) - public CompletionStage searchExams(Http.Request request, final Optional filter) { - Optional url = filter.orElse("").isEmpty() ? parseUrl() : parseUrlWithSearchParam(filter.get(), false); - if (url.isEmpty()) { - return wrapAsPromise(internalServerError("sitnet_internal_error")); - } - + public CompletionStage searchExams(Http.Request request, Optional filter) { + WSRequest wsRequest = getSearchRequest(filter); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - WSRequest wsRequest = wsClient.url(url.get().toString()); String homeOrg = configReader.getHomeOrganisationRef(); Function onSuccess = response -> @@ -124,7 +114,7 @@ public CompletionStage searchExams(Http.Request request, final Optional< .map(e -> e.getKey().getExam(e.getValue())) .filter(e -> isAuthorizedToView(e, user, homeOrg)) .map(this::serialize) - .collect(Collectors.toList()); + .toList(); return ok(Json.newArray().addAll(exams)); }) @@ -140,11 +130,11 @@ private CompletionStage getExam(Long id, Consumer postProcessor, U downloadExam(ce) .thenApplyAsync(result -> { if (result.isEmpty()) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } Exam exam = result.get(); if (!isAuthorizedToView(exam, user, homeOrg)) { - return notFound("sitnet_error_exam_not_found"); + return notFound("i18n_error_exam_not_found"); } postProcessor.accept(exam); return ok(serialize(exam)); @@ -155,7 +145,7 @@ private CompletionStage getExam(Long id, Consumer postProcessor, U @Restrict({ @Group("ADMIN"), @Group("TEACHER") }) public Result listGradeScales() { - Set grades = Ebean.find(GradeScale.class).fetch("grades").where().isNull("externalRef").findSet(); + Set grades = DB.find(GradeScale.class).fetch("grades").where().isNull("externalRef").findSet(); return ok(grades); } @@ -203,7 +193,7 @@ public CompletionStage deleteExam(Long id) { return findCollaborativeExam(id) .map(ce -> { if (!ce.getState().equals(Exam.State.DRAFT) && !ce.getState().equals(Exam.State.PRE_PUBLISHED)) { - return wrapAsPromise(forbidden("sitnet_exam_removal_not_possible")); + return wrapAsPromise(forbidden("i18n_exam_removal_not_possible")); } return examLoader .deleteExam(ce) @@ -270,7 +260,7 @@ public CompletionStage updateExam(Long id, Http.Request request) { return result2; }); } - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } return wrapAsPromise(notFound()); }); diff --git a/app/controllers/iop/collaboration/impl/CollaborativeExamLoaderImpl.java b/app/controllers/iop/collaboration/impl/CollaborativeExamLoaderImpl.java index 17dbd9bc7e..ed792eb987 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeExamLoaderImpl.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeExamLoaderImpl.java @@ -5,11 +5,12 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.iop.collaboration.api.CollaborativeExamLoader; import controllers.iop.transfer.api.ExternalAttachmentLoader; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Model; import io.ebean.text.PathProperties; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -21,7 +22,8 @@ import models.User; import models.json.CollaborativeExam; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; @@ -33,7 +35,7 @@ public class CollaborativeExamLoaderImpl implements CollaborativeExamLoader { private static final int OK = 200; - private static final Logger.ALogger logger = Logger.of(CollaborativeExamLoaderImpl.class); + private final Logger logger = LoggerFactory.getLogger(CollaborativeExamLoaderImpl.class); @Inject WSClient wsClient; @@ -50,9 +52,9 @@ private Optional parseUrl(String examRef) { sb.append(String.format("/%s", examRef)); } try { - return Optional.of(new URL(sb.toString())); + return Optional.of(URI.create(sb.toString()).toURL()); } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); + logger.error("Malformed URL", e); return Optional.empty(); } } @@ -60,10 +62,10 @@ private Optional parseUrl(String examRef) { private Optional parseAssessmentUrl(String examRef) { try { return Optional.of( - new URL(configReader.getIopHost() + String.format("/api/exams/%s/assessments", examRef)) + URI.create(configReader.getIopHost() + String.format("/api/exams/%s/assessments", examRef)).toURL() ); } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); + logger.error("Malformed URL", e); return Optional.empty(); } } @@ -83,9 +85,9 @@ private JsonNode serializeForUpdate(Exam exam, String revision) { private Optional parseUrl(String examRef, String assessmentRef) { String url = String.format("%s/api/exams/%s/assessments/%s", configReader.getIopHost(), examRef, assessmentRef); try { - return Optional.of(new URL(url)); + return Optional.of(URI.create(url).toURL()); } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); + logger.error("Malformed URL", e); return Optional.empty(); } } @@ -114,7 +116,7 @@ public PathProperties getAssessmentPath() { @Override public CompletionStage createAssessmentWithAttachments(ExamParticipation participation) { String ref = participation.getCollaborativeExam().getExternalRef(); - logger.debug("Sending back collaborative assessment for exam " + ref); + logger.debug("Sending back collaborative assessment for exam {}", ref); Optional ou = parseAssessmentUrl(ref); if (ou.isEmpty()) { return CompletableFuture.completedFuture(false); @@ -127,7 +129,7 @@ public CompletionStage createAssessmentWithAttachments(ExamParticipatio @Override public CompletionStage createAssessment(ExamParticipation participation) { String ref = participation.getCollaborativeExam().getExternalRef(); - logger.debug("Sending back collaborative assessment for exam " + ref); + logger.debug("Sending back collaborative assessment for exam {}", ref); Optional ou = parseAssessmentUrl(ref); if (ou.isEmpty()) { return CompletableFuture.completedFuture(false); @@ -135,20 +137,20 @@ public CompletionStage createAssessment(ExamParticipation participation WSRequest request = wsClient.url(ou.get().toString()).setContentType("application/json"); Function onSuccess = response -> { if (response.getStatus() != Http.Status.CREATED) { - logger.error("Failed in sending assessment for exam " + ref); + logger.error("Failed in sending assessment for exam {}", ref); return false; } participation.setSentForReview(DateTime.now()); participation.update(); - logger.info("Assessment for exam " + ref + " processed successfully"); + logger.info("Assessment for exam {} processed successfully", ref); return true; }; return request - .post(Ebean.json().toJson(participation, getAssessmentPath())) + .post(DB.json().toJson(participation, getAssessmentPath())) .thenApplyAsync(onSuccess) .exceptionally(t -> { - logger.error("Could not send assessment to xm! [id=" + participation.getId() + "]", t); + logger.error(String.format("Could not send assessment to xm! [id=%s]", participation.getId()), t); return false; }); } @@ -185,10 +187,10 @@ public CompletionStage> downloadExam(CollaborativeExam ce) { } ce.setRevision(root.get("_rev").asText()); Exam exam = ce.getExam(root); - // Save certain informative properties locally so we can display them right away in some cases + // Save certain informative properties locally, so we can display them right away in some cases ce.setName(exam.getName()); - ce.setExamActiveStartDate(exam.getExamActiveStartDate()); - ce.setExamActiveEndDate(exam.getExamActiveEndDate()); + ce.setPeriodStart(exam.getPeriodStart()); + ce.setPeriodEnd(exam.getPeriodEnd()); ce.setEnrollInstruction(exam.getEnrollInstruction()); ce.setDuration(exam.getDuration()); ce.setHash(exam.getHash()); @@ -262,7 +264,7 @@ private CompletionStage defer(Result result) { } protected Result ok(Object object, PathProperties pp) { - String body = pp == null ? Ebean.json().toJson(object) : Ebean.json().toJson(object, pp); + String body = pp == null ? DB.json().toJson(object) : DB.json().toJson(object, pp); return Results.ok(body).as("application/json"); } } diff --git a/app/controllers/iop/collaboration/impl/CollaborativeExamSectionController.java b/app/controllers/iop/collaboration/impl/CollaborativeExamSectionController.java index bd99e04486..a7caf8e39a 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeExamSectionController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeExamSectionController.java @@ -30,7 +30,6 @@ import java.util.concurrent.CompletionStage; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.stream.Collectors; import java.util.stream.Stream; import models.Exam; import models.User; @@ -64,7 +63,7 @@ public CompletionStage addSection(Long examId, Http.Request request) { exam.getExamSections().add(section); return uploadExam(ce, exam, user, section, null); } - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } return wrapAsPromise(notFound()); }); @@ -96,7 +95,7 @@ private CompletionStage update( ); return uploadExam(ce, exam, user, resultProvider.apply(exam).orElse(null), pp); } - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } return wrapAsPromise(notFound()); }); @@ -115,18 +114,18 @@ public CompletionStage removeSection(Long examId, Long sectionId, Http.R .findFirst(); if (section.isPresent()) { ExamSection es = section.get(); - exam.getExamSections().remove(section.get()); + exam.getExamSections().remove(es); // Decrease sequences for the entries above the inserted one int seq = es.getSequenceNumber(); for (ExamSection sibling : exam.getExamSections()) { int num = sibling.getSequenceNumber(); if (num >= seq) { - es.setSequenceNumber(num - 1); + sibling.setSequenceNumber(num - 1); } } return Optional.empty(); } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } }; @@ -156,7 +155,7 @@ public CompletionStage updateSection(Long examId, Long sectionId, Http.R es.setDescription(form.getDescription()); return Optional.empty(); } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } }; @@ -226,7 +225,7 @@ public CompletionStage reorderSectionQuestions(Long examId, Long section } return Optional.empty(); } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } }; return update(request, examId, updater, e -> Optional.empty()); @@ -247,6 +246,7 @@ public CompletionStage addQuestion(Long examId, Long sectionId, Http.Req ExamSection es = section.get(); JsonNode questionBody = request.body().asJson().get("question"); Question question = JsonDeserializer.deserialize(Question.class, questionBody); + question.getQuestionOwners().forEach(this::cleanUser); Optional error = question.getValidationResult(questionBody); if (error.isPresent()) { return error; @@ -262,7 +262,7 @@ public CompletionStage addQuestion(Long examId, Long sectionId, Http.Req .generate(this::newId) .limit(options.size()) .sorted(Comparator.naturalOrder()) - .collect(Collectors.toList()); + .toList(); for (int i = 0; i < options.size(); i++) { options.get(i).setId(generatedIds.get(i)); } @@ -276,7 +276,7 @@ public CompletionStage addQuestion(Long examId, Long sectionId, Http.Req updateSequences(es.getSectionQuestions(), sequence); esq.setSequenceNumber(sequence); if (es.getSectionQuestions().contains(esq) || es.hasQuestion(question)) { - return Optional.of(badRequest("sitnet_question_already_in_section")); + return Optional.of(badRequest("i18n_question_already_in_section")); } if (question.getType().equals(Question.Type.EssayQuestion)) { // disable auto evaluation for this exam @@ -295,7 +295,7 @@ public CompletionStage addQuestion(Long examId, Long sectionId, Http.Req es.getSectionQuestions().add(esq); return Optional.empty(); } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } }; return update( @@ -346,10 +346,10 @@ public CompletionStage removeQuestion(Long examId, Long sectionId, Long } return Optional.empty(); } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } }; return update( @@ -374,7 +374,7 @@ public CompletionStage clearQuestions(Long examId, Long sectionId, Http. es.getSectionQuestions().clear(); return Optional.empty(); } else { - return Optional.of(notFound("sitnet_error_not_found")); + return Optional.of(notFound("i18n_error_not_found")); } }; return update( @@ -429,13 +429,13 @@ public CompletionStage updateQuestion(Long examId, Long sectionId, Long ); return uploadExam(ce, exam, user, esq, pp); } else { - return wrapAsPromise(notFound("sitnet_error_not_found")); + return wrapAsPromise(notFound("i18n_error_not_found")); } } else { - return wrapAsPromise(notFound("sitnet_error_not_found")); + return wrapAsPromise(notFound("i18n_error_not_found")); } } - return wrapAsPromise(forbidden("sitnet_error_access_forbidden")); + return wrapAsPromise(forbidden("i18n_error_access_forbidden")); } return wrapAsPromise(notFound()); }); diff --git a/app/controllers/iop/collaboration/impl/CollaborativeExternalCalendarController.java b/app/controllers/iop/collaboration/impl/CollaborativeExternalCalendarController.java index 39364b2f93..c6ab6d12bc 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeExternalCalendarController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeExternalCalendarController.java @@ -7,8 +7,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import exceptions.NotFoundException; import impl.CalendarHandler; -import io.ebean.Ebean; +import io.ebean.DB; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Collection; import java.util.Optional; @@ -32,20 +33,12 @@ import sanitizers.Attrs; import sanitizers.ExternalCalendarReservationSanitizer; import security.Authenticated; -import util.config.ConfigReader; -import util.datetime.DateTimeHandler; public class CollaborativeExternalCalendarController extends CollaborativeCalendarController { @Inject CalendarHandler calendarHandler; - @Inject - private ConfigReader configReader; - - @Inject - private DateTimeHandler dateTimeHandler; - @Authenticated @With(ExternalCalendarReservationSanitizer.class) @Restrict({ @Group("STUDENT") }) @@ -63,11 +56,11 @@ public CompletionStage requestReservation(Http.Request request) { Collection sectionIds = request.attrs().get(Attrs.SECTION_IDS); DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, examId); + CollaborativeExam ce = DB.find(CollaborativeExam.class, examId); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } - final ExamEnrolment enrolment = Ebean + final ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .where() @@ -79,12 +72,12 @@ public CompletionStage requestReservation(Http.Request request) { .endJunction() .findOne(); if (enrolment == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } return downloadExam(ce) .thenComposeAsync(result -> { if (result.isEmpty()) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } Exam exam = result.get(); Optional badEnrolment = checkEnrolment(enrolment, exam, user); @@ -151,22 +144,22 @@ public CompletionStage requestSlots( ) { if (org.isPresent() && date.isPresent()) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, examId); + CollaborativeExam ce = DB.find(CollaborativeExam.class, examId); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } ExamEnrolment enrolment = getEnrolledExam(examId, user); if (enrolment == null) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_not_found")); + return wrapAsPromise(forbidden("i18n_error_enrolment_not_found")); } return downloadExam(ce) .thenComposeAsync(result -> { if (result.isEmpty()) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } Exam exam = result.get(); if (!exam.hasState(Exam.State.PUBLISHED)) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } // Also sanity check the provided search date try { @@ -175,8 +168,8 @@ public CompletionStage requestSlots( return wrapAsPromise(notFound()); } // Ready to shoot - String start = ISODateTimeFormat.dateTime().print(new DateTime(exam.getExamActiveStartDate())); - String end = ISODateTimeFormat.dateTime().print(new DateTime(exam.getExamActiveEndDate())); + String start = ISODateTimeFormat.dateTime().print(new DateTime(exam.getPeriodStart())); + String end = ISODateTimeFormat.dateTime().print(new DateTime(exam.getPeriodEnd())); Integer duration = exam.getDuration(); URL url = parseUrl(org.get(), roomRef, date.get(), start, end, duration); WSRequest wsRequest = wsClient.url(url.toString().split("\\?")[0]).setQueryString(url.getQuery()); @@ -201,7 +194,7 @@ public CompletionStage requestSlots( private ExamEnrolment getEnrolledExam(Long examId, User user) { DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - return Ebean + return DB .find(ExamEnrolment.class) .where() .eq("user", user) @@ -214,10 +207,12 @@ private ExamEnrolment getEnrolledExam(Long examId, User user) { } private URL parseUrl(String orgRef, String facilityRef) throws MalformedURLException { - return new URL( - configReader.getIopHost() + - String.format("/api/organisations/%s/facilities/%s/reservations", orgRef, facilityRef) - ); + return URI + .create( + configReader.getIopHost() + + String.format("/api/organisations/%s/facilities/%s/reservations", orgRef, facilityRef) + ) + .toURL(); } private URL parseUrl(String orgRef, String facilityRef, String date, String start, String end, int duration) { @@ -226,7 +221,7 @@ private URL parseUrl(String orgRef, String facilityRef, String date, String star String.format("/api/organisations/%s/facilities/%s/slots", orgRef, facilityRef) + String.format("?date=%s&startAt=%s&endAt=%s&duration=%d", date, start, end, duration); try { - return new URL(url); + return URI.create(url).toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } diff --git a/app/controllers/iop/collaboration/impl/CollaborativeReviewController.java b/app/controllers/iop/collaboration/impl/CollaborativeReviewController.java index 6ebde78602..3980b0480a 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeReviewController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeReviewController.java @@ -15,18 +15,18 @@ package controllers.iop.collaboration.impl; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import io.vavr.control.Either; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Collection; import java.util.Iterator; @@ -45,10 +45,12 @@ import models.json.CollaborativeExam; import models.questions.ClozeTestAnswer; import models.questions.Question; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import org.joda.time.format.ISODateTimeFormat; -import org.springframework.util.StringUtils; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; import play.i18n.Lang; import play.i18n.MessagesApi; import play.libs.Json; @@ -91,7 +93,7 @@ public class CollaborativeReviewController extends CollaborationController { @Inject ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(CollaborativeReviewController.class); + private final Logger logger = LoggerFactory.getLogger(CollaborativeReviewController.class); private Optional parseUrl(String examRef, String assessmentRef) { String url = String.format("%s/api/exams/%s/assessments", configReader.getIopHost(), examRef); @@ -99,9 +101,9 @@ private Optional parseUrl(String examRef, String assessmentRef) { url += String.format("/%s", assessmentRef); } try { - return Optional.of(new URL(url)); + return Optional.of(URI.create(url).toURL()); } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); + logger.error("Malformed URL", e); return Optional.empty(); } } @@ -121,7 +123,7 @@ private Result handleSingleAssessmentResponse(Http.Request request, WSResponse r esq.get("question").get("type").textValue().equals(Question.Type.ClozeTestQuestion.toString()) ) .forEach(esq -> { - if (!esq.get("clozeTestAnswer").isObject() || esq.get("clozeTestAnswer").size() == 0) { + if (!esq.get("clozeTestAnswer").isObject() || esq.get("clozeTestAnswer").isEmpty()) { ((ObjectNode) esq).set("clozeTestAnswer", Json.newObject()); } ClozeTestAnswer cta = JsonDeserializer.deserialize(ClozeTestAnswer.class, esq.get("clozeTestAnswer")); @@ -158,7 +160,7 @@ private void scoreAnswer(JsonNode examNode, Long qid, Double score) { .findAny() .ifPresent(esq -> { JsonNode essayAnswer = esq.get("essayAnswer"); - if (essayAnswer.isObject() && essayAnswer.size() > 0) { + if (essayAnswer.isObject() && !essayAnswer.isEmpty()) { ((ObjectNode) essayAnswer).put("evaluatedScore", score); } else { ((ObjectNode) essayAnswer).set("essayAnswer", Json.newObject().put("evaluatedScore", score)); @@ -212,7 +214,7 @@ public CompletionStage getParticipationsForExamAndUser(Long eid, String return notFound("Assessment not found!"); } final String eppn = assessment.get().path("user").path("eppn").textValue(); - if (StringUtils.isEmpty(eppn)) { + if (ObjectUtils.isEmpty(eppn)) { return notFound("Eppn not found!"); } // Filter for user eppn and left out assessment that we currently are looking. @@ -274,7 +276,7 @@ public CompletionStage exportAssessments(Long id, Http.Request request) try { file = csvBuilder.build(root); } catch (IOException e) { - return internalServerError("sitnet_error_creating_csv_file"); + return internalServerError("i18n_error_creating_csv_file"); } String contentDisposition = fileHandler.getContentDisposition(file); return ok(fileHandler.encodeAndDelete(file)) @@ -405,9 +407,9 @@ public CompletionStage sendInspectionMessage(Long id, String ref, Http.R @Authenticated @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public CompletionStage forceUpdateAnswerScore(Long id, String ref, Long qid, Http.Request request) { - CollaborativeExam ce = Ebean.find(CollaborativeExam.class, id); + CollaborativeExam ce = DB.find(CollaborativeExam.class, id); if (ce == null) { - return wrapAsPromise(notFound("sitnet_error_exam_not_found")); + return wrapAsPromise(notFound("i18n_error_exam_not_found")); } Optional url = parseUrl(ce.getExternalRef(), ref); if (url.isEmpty()) { @@ -441,6 +443,7 @@ public CompletionStage updateAssessment(Long id, String ref, Http.Reques } JsonNode body = request.body().asJson(); User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + cleanUser(user); WSRequest wsRequest = wsClient.url(url.get().toString()); Function> onSuccess = response -> { JsonNode root = response.asJson(); @@ -463,7 +466,7 @@ public CompletionStage updateAssessment(Long id, String ref, Http.Reques return wrapAsPromise(forbidden("Not allowed to update grading of this exam")); } JsonNode grade = body.get("grade"); - if (grade != null && grade.isObject() && grade.size() > 0) { + if (grade != null && grade.isObject() && !grade.isEmpty()) { boolean validGrade = exam .getGradeScale() .getGrades() @@ -472,6 +475,7 @@ public CompletionStage updateAssessment(Long id, String ref, Http.Reques .anyMatch(i -> i == grade.get("id").asInt()); if (validGrade) { ((ObjectNode) examNode).set("grade", grade); + ((ObjectNode) examNode).put("gradeless", false); } else { return wrapAsPromise(badRequest("Invalid grade for this grade scale")); } @@ -629,7 +633,7 @@ private Optional> validateExamState(Exam exam, boolean g exam.hasState(Exam.State.ABORTED, Exam.State.GRADED_LOGGED, Exam.State.ARCHIVED) || exam.getExamRecord() != null ) { - return Optional.of(wrapAsPromise(forbidden("sitnet_error_exam_already_graded_logged"))); + return Optional.of(wrapAsPromise(forbidden("i18n_error_exam_already_graded_logged"))); } return Optional.empty(); } @@ -638,6 +642,7 @@ private Optional> validateExamState(Exam exam, boolean g @Restrict({ @Group("TEACHER"), @Group("ADMIN") }) public CompletionStage finalizeAssessment(Long id, String ref, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); + cleanUser(user); JsonNode body = request.body().asJson(); return findCollaborativeExam(id) .map(ce -> diff --git a/app/controllers/iop/collaboration/impl/CollaborativeStudentActionController.java b/app/controllers/iop/collaboration/impl/CollaborativeStudentActionController.java index 20c8705b8e..c38da0a04a 100644 --- a/app/controllers/iop/collaboration/impl/CollaborativeStudentActionController.java +++ b/app/controllers/iop/collaboration/impl/CollaborativeStudentActionController.java @@ -20,12 +20,14 @@ import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.concurrent.CompletionStage; import javax.inject.Inject; import models.User; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.mvc.Http; @@ -38,7 +40,7 @@ public class CollaborativeStudentActionController extends CollaborationControlle private final WSClient wsClient; - private static final Logger.ALogger logger = Logger.of(CollaborativeStudentActionController.class); + private final Logger logger = LoggerFactory.getLogger(CollaborativeStudentActionController.class); @Inject public CollaborativeStudentActionController(WSClient wsClient) { @@ -53,7 +55,7 @@ public CompletionStage getFinishedExams(Http.Request request) { if (url.isEmpty()) { return wrapAsPromise(internalServerError()); } - final WSRequest wsRequest = wsClient.url(url.get().toString() + user.getEppn()); + final WSRequest wsRequest = wsClient.url(url.get() + user.getEppn()); return wsRequest .get() .thenComposeAsync(response -> { @@ -69,9 +71,9 @@ public CompletionStage getFinishedExams(Http.Request request) { Optional parseUrl() { String url = String.format("%s/api/assessments/user?eppn=", configReader.getIopHost()); try { - return Optional.of(new URL(url)); + return Optional.of(URI.create(url).toURL()); } catch (MalformedURLException e) { - logger.error("Malformed URL {}", e); + logger.error("Malformed URL", e); return Optional.empty(); } } diff --git a/app/controllers/iop/transfer/impl/DataTransferController.java b/app/controllers/iop/transfer/impl/DataTransferController.java index a7bec79208..c8dc54003a 100644 --- a/app/controllers/iop/transfer/impl/DataTransferController.java +++ b/app/controllers/iop/transfer/impl/DataTransferController.java @@ -1,9 +1,5 @@ package controllers.iop.transfer.impl; -import akka.stream.IOResult; -import akka.stream.javadsl.FileIO; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import be.objectify.deadbolt.java.actions.SubjectNotPresent; @@ -11,12 +7,13 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Query; import io.ebean.text.PathProperties; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Path; import java.util.List; @@ -32,7 +29,12 @@ import models.Tag; import models.User; import models.questions.Question; -import play.Logger; +import org.apache.pekko.stream.IOResult; +import org.apache.pekko.stream.javadsl.FileIO; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.http.HttpErrorHandler; import play.libs.Files; import play.libs.Json; @@ -50,7 +52,7 @@ public class DataTransferController extends BaseController { - private static final Logger.ALogger logger = Logger.of(DataTransferController.class); + private final Logger logger = LoggerFactory.getLogger(DataTransferController.class); static class DataTransferBodyParser extends BodyParser.Json { @@ -79,7 +81,7 @@ enum DataType { @SubjectNotPresent public Result importQuestionAttachment(Long id, Http.Request request) { - Question question = Ebean.find(Question.class, id); + Question question = DB.find(Question.class, id); if (question == null) { return notFound(); } @@ -89,13 +91,13 @@ public Result importQuestionAttachment(Long id, Http.Request request) { throw new IllegalArgumentException("file not found"); } if (filePart.getFileSize() > configReader.getMaxFileSize()) { - throw new IllegalArgumentException("sitnet_file_too_large"); + throw new IllegalArgumentException("i18n_file_too_large"); } String newFilePath; try { newFilePath = copyFile(filePart.getRef(), "question", Long.toString(id)); } catch (IOException e) { - return internalServerError("sitnet_error_creating_attachment"); + return internalServerError("i18n_error_creating_attachment"); } // Remove existing one if found fileHandler.removePrevious(question); @@ -133,7 +135,7 @@ public CompletionStage exportData(Http.Request request) throws IOExcepti .map(JsonNode::asLong) .collect(Collectors.toSet()); PathProperties pp = PathProperties.parse("(*, options(*), tags(name))"); - Query query = Ebean.find(Question.class); + Query query = DB.find(Question.class); query.apply(pp); Set questions = query .where() @@ -147,12 +149,7 @@ public CompletionStage exportData(Http.Request request) throws IOExcepti JsonNode data = ((ObjectNode) body).put("path", path) .put("owner", user.getEppn()) - .set( - "questions", - Json - .newArray() - .addAll(questions.stream().map(q -> serialize(q, pp)).collect(Collectors.toList())) - ); + .set("questions", Json.newArray().addAll(questions.stream().map(q -> serialize(q, pp)).toList())); URL url = parseURL(body.get("orgRef").asText()); String uploadUrl = parseUploadURL(body.get("orgRef").asText()); @@ -189,7 +186,10 @@ public CompletionStage exportData(Http.Request request) throws IOExcepti req .post(createSource(ra.getValue())) .exceptionally(e -> { - logger.error("failed in uploading attachment id " + ra.getKey(), e); + logger.error( + String.format("failed in uploading attachment id %s", ra.getKey()), + e + ); return null; }) ); @@ -206,23 +206,19 @@ public CompletionStage exportData(Http.Request request) throws IOExcepti Attachment attachment ) { Source> source = FileIO.fromPath(Path.of(attachment.getFilePath())); - Http.MultipartFormData.FilePart>> filePart = new Http.MultipartFormData.FilePart<>( - "file", - attachment.getFileName(), - attachment.getMimeType(), - source - ); + Http.MultipartFormData.FilePart>> filePart = + new Http.MultipartFormData.FilePart<>("file", attachment.getFileName(), attachment.getMimeType(), source); return Source.from(Set.of(filePart)); } private URL parseURL(String orgRef) throws MalformedURLException { String url = String.format("%s/api/organisations/%s/export", configReader.getIopHost(), orgRef); - return new URL(url); + return URI.create(url).toURL(); } private String parseUploadURL(String orgRef) throws MalformedURLException { String url = String.format("%s/api/organisations/%s/export/id/attachment", configReader.getIopHost(), orgRef); - return new URL(url).toString(); + return URI.create(url).toURL().toString(); } private boolean isNewTag(Tag tag, List existing) { @@ -242,7 +238,7 @@ private static class QuestionEntry { private Result importQuestions(JsonNode node) { String eppn = node.get("owner").asText(); - Optional ou = Ebean.find(User.class).where().eq("eppn", eppn).findOneOrEmpty(); + Optional ou = DB.find(User.class).where().eq("eppn", eppn).findOneOrEmpty(); if (ou.isEmpty()) { return badRequest("User not recognized"); } @@ -257,17 +253,11 @@ private Result importQuestions(JsonNode node) { copy.setCreatorWithDate(user); copy.setModifierWithDate(user); copy.save(); - List userTags = Ebean.find(Tag.class).where().eq("creator", user).findList(); - List newTags = question - .getTags() - .stream() - .filter(t -> isNewTag(t, userTags)) - .collect(Collectors.toList()); + List userTags = DB.find(Tag.class).where().eq("creator", user).findList(); + List newTags = question.getTags().stream().filter(t -> isNewTag(t, userTags)).toList(); newTags.forEach(t -> t.setId(null)); - List existingTags = userTags - .stream() - .filter(t -> !isNewTag(t, question.getTags())) - .collect(Collectors.toList()); + List existingTags = userTags.stream().filter(t -> !isNewTag(t, question.getTags())).toList(); + DB.saveAll(newTags); copy.getTags().addAll(newTags); copy.getTags().addAll(existingTags); copy.getTags().forEach(t -> t.setCreatorWithDate(user)); @@ -275,10 +265,10 @@ private Result importQuestions(JsonNode node) { copy.getQuestionOwners().clear(); copy.getQuestionOwners().add(user); copy.update(); - Ebean.saveAll(copy.getOptions()); + DB.saveAll(copy.getOptions()); return new QuestionEntry(question.getId(), copy.getId()); }) - .collect(Collectors.toList()); + .toList(); ArrayNode an = Json.newArray(); entries.forEach(entry -> an.add(Json.newObject().put("src", entry.srcId).put("dst", entry.dstId))); return Results.created((JsonNode) Json.newObject().set("ids", an)); diff --git a/app/controllers/iop/transfer/impl/ExternalAttachmentController.java b/app/controllers/iop/transfer/impl/ExternalAttachmentController.java index b6e70bda6b..0a87413267 100644 --- a/app/controllers/iop/transfer/impl/ExternalAttachmentController.java +++ b/app/controllers/iop/transfer/impl/ExternalAttachmentController.java @@ -18,7 +18,7 @@ import controllers.base.BaseController; import controllers.iop.transfer.api.ExternalAttachmentInterface; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import java.io.IOException; import java.util.Optional; @@ -76,7 +76,7 @@ public Optional getExam(ExternalExam externalExam) { @Override public Optional getExternalExam(String id, Http.Request request) { final User user = getUser(request); - final ExpressionList query = Ebean.find(ExternalExam.class).where().eq("hash", id); + final ExpressionList query = DB.find(ExternalExam.class).where().eq("hash", id); if (user.hasRole(Role.Name.STUDENT)) { query.eq("creator", user); } diff --git a/app/controllers/iop/transfer/impl/ExternalAttachmentLoaderImpl.java b/app/controllers/iop/transfer/impl/ExternalAttachmentLoaderImpl.java index 81ee3d555f..1f93dc91d4 100644 --- a/app/controllers/iop/transfer/impl/ExternalAttachmentLoaderImpl.java +++ b/app/controllers/iop/transfer/impl/ExternalAttachmentLoaderImpl.java @@ -16,16 +16,11 @@ package controllers.iop.transfer.impl; -import akka.actor.ActorSystem; -import akka.stream.IOResult; -import akka.stream.Materializer; -import akka.stream.javadsl.FileIO; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import com.fasterxml.jackson.databind.JsonNode; import controllers.iop.transfer.api.ExternalAttachmentLoader; import java.io.File; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Paths; import java.util.ArrayList; @@ -36,8 +31,15 @@ import javax.inject.Inject; import models.Attachment; import models.Exam; -import org.springframework.util.StringUtils; -import play.Logger; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.stream.IOResult; +import org.apache.pekko.stream.Materializer; +import org.apache.pekko.stream.javadsl.FileIO; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.mvc.Http; @@ -58,7 +60,7 @@ public class ExternalAttachmentLoaderImpl implements ExternalAttachmentLoader { @Inject private ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(ExternalAttachmentLoaderImpl.class); + private final Logger logger = LoggerFactory.getLogger(ExternalAttachmentLoaderImpl.class); @Override public CompletableFuture fetchExternalAttachmentsAsLocal(Exam exam) { @@ -98,7 +100,7 @@ public CompletableFuture fetchExternalAttachmentsAsLocal(Exam exam) { @Override public CompletableFuture createExternalAttachment(Attachment attachment) { - if (attachment == null || StringUtils.isEmpty(attachment.getFilePath())) { + if (attachment == null || ObjectUtils.isEmpty(attachment.getFilePath())) { return CompletableFuture.completedFuture(null); } final URL attachmentUrl; @@ -134,12 +136,13 @@ public CompletableFuture createExternalAttachment(Attachment attachment) { return; } final Source> source = FileIO.fromPath(file.toPath()); - final Http.MultipartFormData.FilePart>> filePart = new Http.MultipartFormData.FilePart<>( - "file", - attachment.getFileName(), - attachment.getMimeType(), - source - ); + final Http.MultipartFormData.FilePart>> filePart = + new Http.MultipartFormData.FilePart<>( + "file", + attachment.getFileName(), + attachment.getMimeType(), + source + ); Http.MultipartFormData.DataPart dp = new Http.MultipartFormData.DataPart("key", "value"); updateRequest @@ -182,7 +185,7 @@ public CompletableFuture uploadAssessmentAttachments(Exam exam) { private CompletableFuture createFromExternalAttachment(Attachment attachment, String... pathParams) { return CompletableFuture.runAsync(() -> { - if (StringUtils.isEmpty(attachment.getExternalId())) { + if (ObjectUtils.isEmpty(attachment.getExternalId())) { logger.error("Could not find external ID for an attachment"); return; } @@ -215,6 +218,6 @@ private CompletableFuture createFromExternalAttachment(Attachment attachme private URL parseUrl(String format, Object... args) throws MalformedURLException { final String path = args.length < 1 ? format : String.format(format, args); - return new URL(configReader.getIopHost() + path); + return URI.create(configReader.getIopHost() + path).toURL(); } } diff --git a/app/controllers/iop/transfer/impl/ExternalCalendarController.java b/app/controllers/iop/transfer/impl/ExternalCalendarController.java index 5aaece2b0b..93fef8e2fc 100644 --- a/app/controllers/iop/transfer/impl/ExternalCalendarController.java +++ b/app/controllers/iop/transfer/impl/ExternalCalendarController.java @@ -24,9 +24,10 @@ import controllers.CalendarController; import exceptions.NotFoundException; import impl.CalendarHandler; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collection; @@ -39,7 +40,6 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; import java.util.stream.Collector; -import java.util.stream.Collectors; import javax.inject.Inject; import models.Exam; import models.ExamEnrolment; @@ -86,26 +86,30 @@ private URL parseUrl(String orgRef, String facilityRef, String date, String star configReader.getIopHost() + String.format("/api/organisations/%s/facilities/%s/slots", orgRef, facilityRef) + String.format("?date=%s&startAt=%s&endAt=%s&duration=%d", date, start, end, duration); - return new URL(url); + return URI.create(url).toURL(); } private URL parseUrl(String orgRef, String facilityRef) throws MalformedURLException { - return new URL( - configReader.getIopHost() + - String.format("/api/organisations/%s/facilities/%s/reservations", orgRef, facilityRef) - ); + return URI + .create( + configReader.getIopHost() + + String.format("/api/organisations/%s/facilities/%s/reservations", orgRef, facilityRef) + ) + .toURL(); } private URL parseUrl(String orgRef, String facilityRef, String reservationRef) throws MalformedURLException { - return new URL( - configReader.getIopHost() + - String.format( - "/api/organisations/%s/facilities/%s/reservations/%s/force", - orgRef, - facilityRef, - reservationRef + return URI + .create( + configReader.getIopHost() + + String.format( + "/api/organisations/%s/facilities/%s/reservations/%s/force", + orgRef, + facilityRef, + reservationRef + ) ) - ); + .toURL(); } // Actions invoked by central IOP server @@ -122,7 +126,7 @@ public Result provideReservation(Http.Request request) { if (start.isBeforeNow() || end.isBefore(start)) { return badRequest("invalid dates"); } - ExamRoom room = Ebean.find(ExamRoom.class).where().eq("externalRef", roomRef).findOne(); + ExamRoom room = DB.find(ExamRoom.class).where().eq("externalRef", roomRef).findOne(); if (room == null) { return notFound("room not found"); } @@ -134,7 +138,7 @@ public Result provideReservation(Http.Request request) { Collections.emptyList() ); if (machine.isEmpty()) { - return forbidden("sitnet_no_machines_available"); + return forbidden("i18n_no_machines_available"); } // We are good to go :) Reservation reservation = new Reservation(); @@ -152,7 +156,7 @@ public Result provideReservation(Http.Request request) { // Initiated by originator of reservation (the student) @SubjectNotPresent public Result acknowledgeReservationRemoval(String ref) { - Reservation reservation = Ebean + Reservation reservation = DB .find(Reservation.class) .fetch("machine") .fetch("machine.room") @@ -165,7 +169,7 @@ public Result acknowledgeReservationRemoval(String ref) { // TODO: might need additional checks DateTime now = dateTimeHandler.adjustDST(DateTime.now(), reservation); if (reservation.toInterval().isBefore(now) || reservation.toInterval().contains(now)) { - return forbidden("sitnet_reservation_in_effect"); + return forbidden("i18n_reservation_in_effect"); } if (reservation.getEnrolment() != null) { reservation.getEnrolment().delete(); // cascades to reservation @@ -178,7 +182,7 @@ public Result acknowledgeReservationRemoval(String ref) { // Initiated by administrator of organisation where reservation takes place @SubjectNotPresent public Result acknowledgeReservationRevocation(String ref) { - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("reservation.externalReservation") @@ -194,7 +198,7 @@ public Result acknowledgeReservationRevocation(String ref) { Reservation reservation = enrolment.getReservation(); DateTime now = dateTimeHandler.adjustDST(DateTime.now(), reservation); if (reservation.toInterval().isBefore(now) || reservation.toInterval().contains(now)) { - return forbidden("sitnet_reservation_in_effect"); + return forbidden("i18n_reservation_in_effect"); } enrolment.setReservation(null); enrolment.update(); @@ -211,7 +215,7 @@ public Result provideSlots( Optional duration ) { if (roomId.isPresent() && date.isPresent() && start.isPresent() && end.isPresent() && duration.isPresent()) { - ExamRoom room = Ebean.find(ExamRoom.class).where().eq("externalRef", roomId.get()).findOne(); + ExamRoom room = DB.find(ExamRoom.class).where().eq("externalRef", roomId.get()).findOne(); if (room == null) { return forbidden(String.format("No room with ref: (%s)", roomId.get())); } @@ -223,7 +227,7 @@ public Result provideSlots( } catch (NotFoundException e) { return notFound(); } - List machines = Ebean + List machines = DB .find(ExamMachine.class) .where() .eq("room.id", room.getId()) @@ -231,7 +235,7 @@ public Result provideSlots( .ne("archived", true) .findList(); // Maintenance periods - List periods = Ebean + List periods = DB .find(MaintenancePeriod.class) .where() .gt("endsAt", searchDate.toDate()) @@ -243,7 +247,7 @@ public Result provideSlots( calendarHandler.normalizeMaintenanceTime(p.getEndsAt()) ) ) - .collect(Collectors.toList()); + .toList(); LocalDate endOfSearch = getEndSearchDate(end.get(), searchDate); while (!searchDate.isAfter(endOfSearch)) { Set timeSlots = getExamSlots( @@ -284,7 +288,7 @@ public CompletionStage requestReservation(Http.Request request) throws M //TODO: See if this offset thing works as intended DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - Optional oe = Ebean + Optional oe = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("exam.examSections") @@ -299,14 +303,14 @@ public CompletionStage requestReservation(Http.Request request) throws M .endOr() .findOneOrEmpty(); if (oe.isEmpty()) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_not_found")); + return wrapAsPromise(forbidden("i18n_error_enrolment_not_found")); } ExamEnrolment enrolment = oe.get(); Optional error = checkEnrolment(enrolment, user, sectionIds); if (error.isPresent()) { return wrapAsPromise(error.get()); } - // Lets do this + // Let's do this URL url = parseUrl(orgRef, roomRef); String homeOrgRef = configReader.getHomeOrganisationRef(); ObjectNode body = Json.newObject(); @@ -352,14 +356,14 @@ public CompletionStage requestReservation(Http.Request request) throws M @Restrict(@Group("STUDENT")) public CompletionStage requestReservationRemoval(String ref, Http.Request request) { User user = request.attrs().get(Attrs.AUTHENTICATED_USER); - Reservation reservation = Ebean.find(Reservation.class).where().eq("externalRef", ref).findOne(); + Reservation reservation = DB.find(Reservation.class).where().eq("externalRef", ref).findOne(); return externalReservationHandler.removeReservation(reservation, user, ""); } @Restrict(@Group("ADMIN")) public CompletionStage requestReservationRevocation(String ref, Http.Request request) throws MalformedURLException { - Optional or = Ebean + Optional or = DB .find(Reservation.class) .where() .isNotNull("machine") @@ -373,7 +377,7 @@ public CompletionStage requestReservationRevocation(String ref, Http.Req Reservation reservation = or.get(); DateTime now = dateTimeHandler.adjustDST(DateTime.now(), reservation); if (reservation.toInterval().isBefore(now) || reservation.toInterval().contains(now)) { - return CompletableFuture.completedFuture(forbidden("sitnet_reservation_in_effect")); + return CompletableFuture.completedFuture(forbidden("i18n_reservation_in_effect")); } String roomRef = reservation.getMachine().getRoom().getExternalRef(); URL url = parseUrl(configReader.getHomeOrganisationRef(), roomRef, reservation.getExternalRef()); @@ -408,7 +412,7 @@ public CompletionStage requestSlots( ExamEnrolment ee = getEnrolment(examId, user); // For now do not allow making an external reservation for collaborative exam if (ee == null || ee.getCollaborativeExam() != null) { - return wrapAsPromise(forbidden("sitnet_error_enrolment_not_found")); + return wrapAsPromise(forbidden("i18n_error_enrolment_not_found")); } Exam exam = ee.getExam(); @@ -419,8 +423,8 @@ public CompletionStage requestSlots( return wrapAsPromise(notFound()); } // Ready to shoot - String start = ISODateTimeFormat.dateTime().print(new DateTime(exam.getExamActiveStartDate())); - String end = ISODateTimeFormat.dateTime().print(new DateTime(exam.getExamActiveEndDate())); + String start = ISODateTimeFormat.dateTime().print(new DateTime(exam.getPeriodStart())); + String end = ISODateTimeFormat.dateTime().print(new DateTime(exam.getPeriodEnd())); Integer duration = exam.getDuration(); URL url = parseUrl(org.get(), roomRef, date.get(), start, end, duration); WSRequest wsRequest = wsClient.url(url.toString().split("\\?")[0]).setQueryString(url.getQuery()); @@ -452,7 +456,7 @@ private Set getExamSlots( .gatherSuitableSlots(room, date, examDuration) .stream() .filter(slot -> maintenances.stream().noneMatch(p -> p.overlaps(slot))) - .collect(Collectors.toList()); + .toList(); // Check machine availability for each slot for (Interval slot : examSlots) { // Check machine availability @@ -484,7 +488,7 @@ private LocalDate parseSearchDate(String day, String startDate, String endDate, .parse(startDate, ISODateTimeFormat.dateTimeParser()) .plusMillis(offset) .toLocalDate(); - LocalDate searchDate = day.equals("") ? now : LocalDate.parse(day, ISODateTimeFormat.dateParser()); + LocalDate searchDate = day.isEmpty() ? now : LocalDate.parse(day, ISODateTimeFormat.dateParser()); searchDate = searchDate.withDayOfWeek(1); if (searchDate.isBefore(now)) { searchDate = now; diff --git a/app/controllers/iop/transfer/impl/ExternalExamController.java b/app/controllers/iop/transfer/impl/ExternalExamController.java index e7988ad9ed..a3580f87e0 100644 --- a/app/controllers/iop/transfer/impl/ExternalExamController.java +++ b/app/controllers/iop/transfer/impl/ExternalExamController.java @@ -15,7 +15,6 @@ package controllers.iop.transfer.impl; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.SubjectNotPresent; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -29,12 +28,13 @@ import impl.AutoEvaluationHandler; import impl.EmailComposer; import impl.NoShowHandler; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Query; import io.ebean.text.PathProperties; import io.ebean.text.json.EJson; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -68,9 +68,11 @@ import models.sections.ExamSection; import models.sections.ExamSectionQuestion; import models.sections.ExamSectionQuestionOption; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; -import play.Logger; import play.db.ebean.Transactional; import play.libs.Json; import play.libs.ws.WSClient; @@ -80,6 +82,7 @@ import play.mvc.Result; import play.mvc.Results; import scala.concurrent.duration.Duration; +import scala.jdk.javaapi.CollectionConverters; import util.AppUtil; import util.config.ConfigReader; import util.json.JsonDeserializer; @@ -110,7 +113,7 @@ public class ExternalExamController extends BaseController implements ExternalEx @Inject private ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(ExternalExamController.class); + private final Logger logger = LoggerFactory.getLogger(ExternalExamController.class); private Exam createCopy(Exam src, Exam parent, User user) { Exam clone = new Exam(); @@ -184,7 +187,7 @@ public CompletionStage addExamForAssessment(String ref, Http.Request req if (ee == null) { return wrapAsPromise(badRequest()); } - Exam parent = Ebean.find(Exam.class).where().eq("hash", ee.getExternalRef()).findOne(); + Exam parent = DB.find(Exam.class).where().eq("hash", ee.getExternalRef()).findOne(); if (parent == null && enrolment.getCollaborativeExam() == null) { return wrapAsPromise(notFound()); } @@ -236,7 +239,12 @@ private void notifyTeachers(Exam exam) { .scheduler() .scheduleOnce( Duration.create(1, TimeUnit.SECONDS), - () -> AppUtil.notifyPrivateExamEnded(recipients, exam, emailComposer), + () -> + AppUtil.notifyPrivateExamEnded( + CollectionConverters.asScala(recipients).toSet(), + exam, + emailComposer + ), actor.dispatcher() ); } @@ -298,7 +306,7 @@ public CompletionStage provideEnrolment(String ref) { .allOf(futures.toArray(new CompletableFuture[0])) .thenComposeAsync(aVoid -> wrapAsPromise(ok(exam, getPath()))) .exceptionally(t -> { - logger.error("Could not provide enrolment [id=" + enrolment.getId() + "]", t); + logger.error(String.format("Could not provide enrolment [id=%s]", enrolment.getId()), t); return internalServerError(); }); } @@ -329,7 +337,7 @@ public CompletionStage requestEnrolment(User user, Reservation re Exam document = JsonDeserializer.deserialize(Exam.class, root); // Set references so that: // - external ref is the reference we got from outside. Must not be changed. - // - local ref is an UUID X. It is used locally for referencing the exam + // - local ref is a UUID X. It is used locally for referencing the exam // - content's hash is set to X in order to simplify things with frontend String externalRef = document.getHash(); @@ -401,6 +409,7 @@ public CompletionStage requestEnrolment(User user, Reservation re enrolment.setExternalExam(ee); enrolment.setReservation(reservation); enrolment.setUser(user); + enrolment.setRandomDelay(); enrolment.save(); return enrolment; }; @@ -408,7 +417,7 @@ public CompletionStage requestEnrolment(User user, Reservation re } private static Query createQuery() { - Query query = Ebean.find(ExamEnrolment.class); + Query query = DB.find(ExamEnrolment.class); PathProperties props = ExaminationController.getPath(true); props.apply(query); return query; @@ -428,6 +437,6 @@ private static Optional getPrototype(String ref) { private URL parseUrl(Object... args) throws MalformedURLException { final String path = args.length < 1 ? "/api/enrolments/%s" : String.format("/api/enrolments/%s", args); - return new URL(configReader.getIopHost() + path); + return URI.create(configReader.getIopHost() + path).toURL(); } } diff --git a/app/controllers/iop/transfer/impl/ExternalExaminationController.java b/app/controllers/iop/transfer/impl/ExternalExaminationController.java index c6c3f74994..7dd2a55b48 100644 --- a/app/controllers/iop/transfer/impl/ExternalExaminationController.java +++ b/app/controllers/iop/transfer/impl/ExternalExaminationController.java @@ -15,7 +15,6 @@ package controllers.iop.transfer.impl; -import akka.actor.ActorSystem; import be.objectify.deadbolt.java.actions.Group; import be.objectify.deadbolt.java.actions.Restrict; import com.fasterxml.jackson.databind.JsonNode; @@ -24,7 +23,7 @@ import controllers.iop.transfer.api.ExternalAttachmentLoader; import impl.AutoEvaluationHandler; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import io.vavr.Tuple; import io.vavr.Tuple2; @@ -37,7 +36,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.function.Function; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; import javax.inject.Inject; import models.Exam; @@ -48,9 +46,10 @@ import models.questions.EssayAnswer; import models.questions.Question; import models.sections.ExamSectionQuestion; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import play.Environment; -import play.libs.concurrent.HttpExecutionContext; +import play.libs.concurrent.ClassLoaderExecutionContext; import play.mvc.Http; import play.mvc.Result; import play.mvc.With; @@ -73,7 +72,7 @@ public ExternalExaminationController( ExaminationRepository examinationRepository, AutoEvaluationHandler autoEvaluationHandler, Environment environment, - HttpExecutionContext httpExecutionContext, + ClassLoaderExecutionContext httpExecutionContext, ExternalAttachmentLoader externalAttachmentLoader, ByodConfigHandler byodConfigHandler, DateTimeHandler dateTimeHandler @@ -184,7 +183,7 @@ public CompletionStage answerMultiChoice(String hash, Long qid, Http.Req List optionIds = StreamSupport .stream(node.spliterator(), false) .map(JsonNode::asLong) - .collect(Collectors.toList()); + .toList(); return findSectionQuestion(ee, qid) .map(t -> processOptions(optionIds, t._2, ee, t._1)) .getOrElseGet(Function.identity()); @@ -225,7 +224,7 @@ public CompletionStage answerEssay(String hash, Long qid, Http.Request r } else if (objectVersion.isPresent()) { if (answer.getObjectVersion() > objectVersion.get()) { // Optimistic locking problem - return forbidden("sitnet_error_data_has_changed"); + return forbidden("i18n_error_data_has_changed"); } answer.setObjectVersion(objectVersion.get() + 1); } @@ -281,7 +280,7 @@ public CompletionStage answerClozeTest(String hash, Long qid, Http.Reque long objectVersion = request.attrs().get(Attrs.OBJECT_VERSION); if (answer.getObjectVersion() > objectVersion) { // Optimistic locking problem - return forbidden("sitnet_error_data_has_changed"); + return forbidden("i18n_error_data_has_changed"); } answer.setObjectVersion(objectVersion + 1); } @@ -318,12 +317,12 @@ private Result processOptions(List oids, ExamSectionQuestion esq, External } private Optional getExternalExam(String hash, User user) { - return Ebean.find(ExternalExam.class).where().eq("hash", hash).eq("creator", user).forUpdate().findOneOrEmpty(); + return DB.find(ExternalExam.class).where().eq("hash", hash).eq("creator", user).forUpdate().findOneOrEmpty(); } private Optional getEnrolment(User user, ExternalExam prototype) { DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("reservation.machine") @@ -339,7 +338,7 @@ private Optional getEnrolment(User user, ExternalExam prototype) } private CompletionStage> getEnrolmentError(String hash, User user, Http.Request request) { - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .eq("externalExam.hash", hash) @@ -350,7 +349,7 @@ private CompletionStage> getEnrolmentError(String hash, User us } private Result terminateExam(String hash, Exam.State newState, User user) { - ExternalExam ee = Ebean.find(ExternalExam.class).where().eq("hash", hash).eq("creator", user).findOne(); + ExternalExam ee = DB.find(ExternalExam.class).where().eq("hash", hash).eq("creator", user).findOne(); if (ee == null) { return forbidden(); } diff --git a/app/controllers/iop/transfer/impl/ExternalReservationHandlerImpl.java b/app/controllers/iop/transfer/impl/ExternalReservationHandlerImpl.java index 984ebbb523..17eddd40b0 100644 --- a/app/controllers/iop/transfer/impl/ExternalReservationHandlerImpl.java +++ b/app/controllers/iop/transfer/impl/ExternalReservationHandlerImpl.java @@ -15,13 +15,13 @@ package controllers.iop.transfer.impl; -import akka.actor.ActorSystem; import com.fasterxml.jackson.databind.JsonNode; import controllers.iop.transfer.api.ExternalReservationHandler; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -33,8 +33,10 @@ import models.Reservation; import models.User; import models.iop.ExternalReservation; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; @@ -62,7 +64,7 @@ public class ExternalReservationHandlerImpl implements ExternalReservationHandle @Inject ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(ExternalReservationHandlerImpl.class); + private final Logger logger = LoggerFactory.getLogger(ExternalReservationHandlerImpl.class); private URL parseUrl(String orgRef, String facilityRef, String reservationRef) throws MalformedURLException { StringBuilder sb = new StringBuilder(configReader.getIopHost()); @@ -70,7 +72,7 @@ private URL parseUrl(String orgRef, String facilityRef, String reservationRef) t if (reservationRef != null) { sb.append("/").append(reservationRef); } - return new URL(sb.toString()); + return URI.create(sb.toString()).toURL(); } @Override @@ -93,7 +95,7 @@ public CompletionStage> removeExternalReservation(Reservation } private CompletionStage requestRemoval(String ref, User user, String msg) throws IOException { - final ExamEnrolment enrolment = Ebean + final ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .fetch("reservation") .fetch("reservation.machine") @@ -111,7 +113,7 @@ private CompletionStage requestRemoval(String ref, User user, String msg final Reservation reservation = enrolment.getReservation(); DateTime now = dateTimeHandler.adjustDST(DateTime.now(), reservation.getExternalReservation()); if (reservation.toInterval().isBefore(now) || reservation.toInterval().contains(now)) { - return CompletableFuture.completedFuture(Results.forbidden("sitnet_reservation_in_effect")); + return CompletableFuture.completedFuture(Results.forbidden("i18n_reservation_in_effect")); } // good to go ExternalReservation external = reservation.getExternalReservation(); @@ -124,7 +126,7 @@ private CompletionStage requestRemoval(String ref, User user, String msg } enrolment.setReservation(null); enrolment.setReservationCanceled(true); - Ebean.save(enrolment); + DB.save(enrolment); reservation.delete(); // send email asynchronously diff --git a/app/controllers/iop/transfer/impl/FacilityController.java b/app/controllers/iop/transfer/impl/FacilityController.java index 7ec1959970..ecf5163265 100644 --- a/app/controllers/iop/transfer/impl/FacilityController.java +++ b/app/controllers/iop/transfer/impl/FacilityController.java @@ -21,9 +21,10 @@ import com.fasterxml.jackson.databind.node.NullNode; import controllers.base.BaseController; import controllers.iop.transfer.api.ExternalFacilityAPI; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -35,6 +36,7 @@ import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; +import play.mvc.Http; import play.mvc.Result; import play.mvc.Results; import util.config.ConfigReader; @@ -54,11 +56,13 @@ private URL parseUrl(String facilityRef) throws MalformedURLException { if (facilityRef != null) { url.append(String.format("/%s", facilityRef)); } - return new URL(url.toString()); + return URI.create(url.toString()).toURL(); } private URL parseExternalUrl(String orgRef) throws MalformedURLException { - return new URL(configReader.getIopHost() + String.format("/api/organisations/%s/facilities", orgRef)); + return URI + .create(configReader.getIopHost() + String.format("/api/organisations/%s/facilities", orgRef)) + .toURL(); } private String toJson(ExamRoom room) { @@ -66,12 +70,12 @@ private String toJson(ExamRoom room) { "(*, defaultWorkingHours(*), calendarExceptionEvents(*), mailAddress(*), " + "examStartingHours(*), accessibilities(*))" ); - return Ebean.json().toJson(room, pp); + return DB.json().toJson(room, pp); } @Restrict({ @Group("ADMIN") }) public CompletionStage updateFacility(Long id) throws MalformedURLException { - ExamRoom room = Ebean.find(ExamRoom.class, id); + ExamRoom room = DB.find(ExamRoom.class, id); if (room == null) { return CompletableFuture.completedFuture(Results.notFound()); } @@ -81,7 +85,7 @@ public CompletionStage updateFacility(Long id) throws MalformedURLExcept // Add new Function onSuccess = response -> { JsonNode root = response.asJson(); - if (response.getStatus() != 201) { + if (response.getStatus() != Http.Status.CREATED) { return internalServerError(root.get("message").asText("Connection refused")); } String externalRef = root.get("id").asText(); @@ -94,7 +98,7 @@ public CompletionStage updateFacility(Long id) throws MalformedURLExcept // Remove Function onSuccess = response -> { int status = response.getStatus(); - if (status == 404 || status == 200) { + if (status == Http.Status.NOT_FOUND || status == Http.Status.OK) { // 404 would mean that facility does not exist remotely, remove its reference here also room.setExternalRef(null); room.update(); @@ -113,14 +117,14 @@ public CompletionStage updateFacility(Long id) throws MalformedURLExcept @Restrict({ @Group("STUDENT") }) public CompletionStage listFacilities(Optional organisation) throws MalformedURLException { - if (!organisation.isPresent()) { + if (organisation.isEmpty()) { return wrapAsPromise(badRequest()); } URL url = parseExternalUrl(organisation.get()); WSRequest request = wsClient.url(url.toString()); Function onSuccess = response -> { JsonNode root = response.asJson(); - if (response.getStatus() != 200) { + if (response.getStatus() != Http.Status.OK) { return internalServerError(root.get("message").asText("Connection refused")); } return ok(root); diff --git a/app/controllers/iop/transfer/impl/OrganisationController.java b/app/controllers/iop/transfer/impl/OrganisationController.java index e783218528..d2b4ac6210 100644 --- a/app/controllers/iop/transfer/impl/OrganisationController.java +++ b/app/controllers/iop/transfer/impl/OrganisationController.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import controllers.base.BaseController; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.concurrent.CompletionStage; import java.util.function.Function; @@ -41,7 +42,7 @@ public class OrganisationController extends BaseController { private ConfigReader configReader; private URL parseUrl() throws MalformedURLException { - return new URL(configReader.getIopHost() + "/api/organisations?withFacilities=true"); + return URI.create(configReader.getIopHost() + "/api/organisations?withFacilities=true").toURL(); } @Restrict({ @Group("STUDENT"), @Group("TEACHER"), @Group("ADMIN") }) @@ -55,8 +56,7 @@ public CompletionStage listOrganisations() throws MalformedURLException if (response.getStatus() != 200) { return internalServerError(root.get("message").asText("Connection refused")); } - if (root instanceof ArrayNode) { - ArrayNode node = (ArrayNode) root; + if (root instanceof ArrayNode node) { for (JsonNode n : node) { ((ObjectNode) n).put("homeOrg", n.get("_id").asText().equals(localRef)); } diff --git a/app/exceptions/MalformedDataException.java b/app/exceptions/MalformedDataException.java index ca4277c2fe..426f5ae9c0 100644 --- a/app/exceptions/MalformedDataException.java +++ b/app/exceptions/MalformedDataException.java @@ -17,8 +17,6 @@ public class MalformedDataException extends RuntimeException { - public MalformedDataException() {} - public MalformedDataException(String message) { super(message); } diff --git a/app/impl/AutoEvaluationHandlerImpl.java b/app/impl/AutoEvaluationHandlerImpl.java index ebb0d75d3e..7fe20e6526 100644 --- a/app/impl/AutoEvaluationHandlerImpl.java +++ b/app/impl/AutoEvaluationHandlerImpl.java @@ -15,7 +15,6 @@ package impl; -import akka.actor.ActorSystem; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; @@ -29,8 +28,10 @@ import models.GradeEvaluation; import models.GradeScale; import models.User; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import scala.concurrent.duration.Duration; public class AutoEvaluationHandlerImpl implements AutoEvaluationHandler { @@ -39,7 +40,7 @@ public class AutoEvaluationHandlerImpl implements AutoEvaluationHandler { private final ActorSystem actor; - private static final Logger.ALogger logger = Logger.of(AutoEvaluationHandlerImpl.class); + private final Logger logger = LoggerFactory.getLogger(AutoEvaluationHandlerImpl.class); @Inject public AutoEvaluationHandlerImpl(EmailComposer composer, ActorSystem actor) { @@ -78,7 +79,7 @@ private void process(Exam exam) { exam.setCreditType(exam.getExamType()); // NOTE: do not set graded by person here, one who makes a record will get the honor if (!exam.getExamLanguages().isEmpty()) { - exam.setAnswerLanguage(exam.getExamLanguages().get(0).getCode()); + exam.setAnswerLanguage(exam.getExamLanguages().getFirst().getCode()); } else { throw new RuntimeException("No exam language found!"); } @@ -106,7 +107,7 @@ private Optional resolveScale(Exam exam) { private Grade getGradeBasedOnScore(Exam exam) { Double totalScore = exam.getTotalScore(); Double maxScore = exam.getMaxScore(); - Double percentage = maxScore == 0 ? 0 : totalScore * 100 / maxScore; + Double percentage = maxScore == 0 ? 0 : (totalScore * 100) / maxScore; List gradeEvaluations = new ArrayList<>(exam.getAutoEvaluationConfig().getGradeEvaluations()); gradeEvaluations.sort(Comparator.comparingInt(GradeEvaluation::getPercentage)); Grade grade = null; diff --git a/app/impl/CalendarHandler.java b/app/impl/CalendarHandler.java index 04b92d1196..82eccc208a 100644 --- a/app/impl/CalendarHandler.java +++ b/app/impl/CalendarHandler.java @@ -4,7 +4,6 @@ import com.google.inject.ImplementedBy; import exceptions.NotFoundException; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -26,7 +25,6 @@ @ImplementedBy(CalendarHandlerImpl.class) public interface CalendarHandler { Result getSlots(User user, Exam exam, Long roomId, String day, Collection aids); - List getEligibleMachines(ExamRoom room, Collection access, Exam exam); Set handleReservations( Map> examSlots, Collection reservations, @@ -106,8 +104,7 @@ public String getConflictingExam() { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof TimeSlot)) return false; - TimeSlot timeSlot = (TimeSlot) o; + if (!(o instanceof TimeSlot timeSlot)) return false; return new EqualsBuilder().append(start, timeSlot.start).append(end, timeSlot.end).build(); } diff --git a/app/impl/CalendarHandlerImpl.java b/app/impl/CalendarHandlerImpl.java index d063f7df0f..70d7847d72 100644 --- a/app/impl/CalendarHandlerImpl.java +++ b/app/impl/CalendarHandlerImpl.java @@ -1,12 +1,11 @@ package impl; -import akka.actor.ActorSystem; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import controllers.SettingsController; import controllers.iop.transfer.api.ExternalReservationHandler; import exceptions.NotFoundException; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -36,6 +35,7 @@ import models.iop.ExternalReservation; import models.json.CollaborativeExam; import models.sections.ExamSection; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; import org.joda.time.DateTimeConstants; import org.joda.time.DateTimeZone; @@ -44,7 +44,8 @@ import org.joda.time.LocalTime; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.Json; import play.mvc.Result; import play.mvc.Results; @@ -54,7 +55,7 @@ public class CalendarHandlerImpl implements CalendarHandler { - private static final Logger.ALogger logger = Logger.of(CalendarHandlerImpl.class); + private final Logger logger = LoggerFactory.getLogger(CalendarHandlerImpl.class); private static final int LAST_HOUR = 23; @Inject @@ -74,7 +75,7 @@ public class CalendarHandlerImpl implements CalendarHandler { @Override public Result getSlots(User user, Exam exam, Long roomId, String day, Collection aids) { - ExamRoom room = Ebean.find(ExamRoom.class, roomId); + ExamRoom room = DB.find(ExamRoom.class, roomId); if (room == null) { return Results.forbidden(String.format("No room with id: (%d)", roomId)); } @@ -92,7 +93,7 @@ public Result getSlots(User user, Exam exam, Long roomId, String day, Collection return Results.notFound(); } // users reservations starting from now - List reservations = Ebean + List reservations = DB .find(Reservation.class) .fetch("enrolment.exam") .where() @@ -102,7 +103,7 @@ public Result getSlots(User user, Exam exam, Long roomId, String day, Collection // Resolve eligible machines based on software and accessibility requirements List machines = getEligibleMachines(room, aids, exam); // Maintenance periods - List periods = Ebean + List periods = DB .find(MaintenancePeriod.class) .where() .gt("endsAt", searchDate.toDate()) @@ -111,8 +112,8 @@ public Result getSlots(User user, Exam exam, Long roomId, String day, Collection .map(p -> new Interval(normalizeMaintenanceTime(p.getStartsAt()), normalizeMaintenanceTime(p.getEndsAt())) ) - .collect(Collectors.toList()); - LocalDate endOfSearch = getEndSearchDate(searchDate, new LocalDate(exam.getExamActiveEndDate())); + .toList(); + LocalDate endOfSearch = getEndSearchDate(searchDate, new LocalDate(exam.getPeriodEnd())); while (!searchDate.isAfter(endOfSearch)) { Set timeSlots = getExamSlots(user, room, exam, searchDate, reservations, machines, periods); if (!timeSlots.isEmpty()) { @@ -129,7 +130,7 @@ public boolean isDoable(Reservation reservation, Collection aids) { DateTimeZone dtz = DateTimeZone.forID(reservation.getMachine().getRoom().getLocalTimezone()); LocalDate searchDate = dateTimeHandler.normalize(reservation.getStartAt().withZone(dtz), dtz).toLocalDate(); // users reservations starting from now - List reservations = Ebean + List reservations = DB .find(Reservation.class) .fetch("enrolment.exam") .where() @@ -143,14 +144,14 @@ public boolean isDoable(Reservation reservation, Collection aids) { reservation.getEnrolment().getExam() ); // Maintenance periods - List periods = Ebean + List periods = DB .find(MaintenancePeriod.class) .where() .gt("endsAt", searchDate.toDate()) .findList() .stream() .map(p -> new Interval(normalizeMaintenanceTime(p.getStartsAt()), normalizeMaintenanceTime(p.getEndsAt()))) - .collect(Collectors.toList()); + .toList(); Set slots = getExamSlots( reservation.getUser(), reservation.getMachine().getRoom(), @@ -173,15 +174,15 @@ public LocalDate parseSearchDate(String day, Exam exam, ExamRoom room) throws No DateTimeZone dtz = room != null ? DateTimeZone.forID(room.getLocalTimezone()) : configReader.getDefaultTimeZone(); - int startOffset = dtz.getOffset((exam.getExamActiveStartDate())); + int startOffset = dtz.getOffset((exam.getPeriodStart())); int offset = dtz.getOffset(DateTime.now()); LocalDate now = DateTime.now().plusMillis(offset).toLocalDate(); LocalDate reservationWindowDate = now.plusDays(windowSize); - LocalDate examEndDate = new DateTime(exam.getExamActiveEndDate()).plusMillis(offset).toLocalDate(); + LocalDate examEndDate = new DateTime(exam.getPeriodEnd()).plusMillis(offset).toLocalDate(); LocalDate searchEndDate = reservationWindowDate.isBefore(examEndDate) ? reservationWindowDate : examEndDate; - LocalDate examStartDate = new DateTime(exam.getExamActiveStartDate()).plusMillis(startOffset).toLocalDate(); - LocalDate searchDate = day.equals("") ? now : ISODateTimeFormat.dateTimeParser().parseLocalDate(day); + LocalDate examStartDate = new DateTime(exam.getPeriodStart()).plusMillis(startOffset).toLocalDate(); + LocalDate searchDate = day.isEmpty() ? now : ISODateTimeFormat.dateTimeParser().parseLocalDate(day); searchDate = searchDate.withDayOfWeek(1); if (searchDate.isBefore(now)) { searchDate = now; @@ -197,9 +198,8 @@ public LocalDate parseSearchDate(String day, Exam exam, ExamRoom room) throws No return searchDate; } - @Override - public List getEligibleMachines(ExamRoom room, Collection access, Exam exam) { - List candidates = Ebean + private List getEligibleMachines(ExamRoom room, Collection access, Exam exam) { + List candidates = DB .find(ExamMachine.class) .fetch("room") .where() @@ -212,7 +212,7 @@ public List getEligibleMachines(ExamRoom room, Collection return candidates .stream() .filter(em -> isMachineAccessibilitySatisfied(em, access) && (exam == null || em.hasRequiredSoftware(exam))) - .collect(Collectors.toList()); + .collect(Collectors.toList()); // needs to be a mutable collection (for shuffling) } @Override @@ -259,7 +259,7 @@ public Collection gatherSuitableSlots(ExamRoom room, LocalDate date, I return !beginning.plusMinutes(examDuration).isAfter(openUntil); }) .map(slot -> new Interval(slot.getStart(), slot.getStart().plusMinutes(examDuration))) - .collect(Collectors.toList()); + .toList(); } return Collections.emptyList(); } @@ -306,7 +306,7 @@ public Set handleReservations( continue; } else { // User has an existing reservation to this exam - Reservation reservation = conflicting.get(0); + Reservation reservation = conflicting.getFirst(); if (!reservation.toInterval().equals(slot)) { // No matching slot found in this room, add the reservation as-is. results.add(new TimeSlot(reservation.toInterval(), -1, null)); @@ -343,7 +343,7 @@ private Set getExamSlots( Collection examSlots = gatherSuitableSlots(room, date, examDuration) .stream() .filter(slot -> maintenancePeriods.stream().noneMatch(p -> p.overlaps(slot))) - .collect(Collectors.toList()); + .toList(); Map> map = examSlots .stream() .collect( @@ -428,7 +428,7 @@ public Set postProcessSlots(JsonNode node, String date ArrayNode root = (ArrayNode) node; LocalDate searchDate = LocalDate.parse(date, ISODateTimeFormat.dateParser()); // users reservations starting from now - List reservations = Ebean + List reservations = DB .find(Reservation.class) .fetch("enrolment.exam") .where() @@ -451,7 +451,7 @@ public Set postProcessSlots(JsonNode node, String date LinkedHashMap::new ) ); - List periods = Ebean + List periods = DB .find(MaintenancePeriod.class) .where() .ge("endsAt", searchDate.withDayOfWeek(DateTimeConstants.MONDAY).toDate()) @@ -460,7 +460,7 @@ public Set postProcessSlots(JsonNode node, String date .map(p -> new Interval(normalizeMaintenanceTime(p.getStartsAt()), normalizeMaintenanceTime(p.getEndsAt())) ) - .collect(Collectors.toList()); + .toList(); // Filter out slots that overlap a local maintenance period Map> map2 = map .entrySet() @@ -531,16 +531,16 @@ public CompletionStage> handleExternalReservation( external.setCampus(roomNode.path("campus").asText()); external.save(); reservation.setExternalReservation(external); - Ebean.save(reservation); + DB.save(reservation); enrolment.setReservation(reservation); enrolment.setReservationCanceled(false); Set sections = sectionIds.isEmpty() ? Collections.emptySet() - : Ebean.find(ExamSection.class).where().idIn(sectionIds).findSet(); + : DB.find(ExamSection.class).where().idIn(sectionIds).findSet(); enrolment.getOptionalSections().clear(); enrolment.update(); enrolment.setOptionalSections(sections); - Ebean.save(enrolment); + DB.save(enrolment); // Finally nuke the old reservation if any if (oldReservation != null) { @@ -549,13 +549,13 @@ public CompletionStage> handleExternalReservation( .removeExternalReservation(oldReservation) .thenApply(err -> { if (err.isEmpty()) { - Ebean.delete(oldReservation); + DB.delete(oldReservation); postProcessRemoval(reservation, exam, user, machineNode); } return err; }); } else { - Ebean.delete(oldReservation); + DB.delete(oldReservation); postProcessRemoval(reservation, exam, user, machineNode); return CompletableFuture.completedFuture(Optional.empty()); } @@ -657,7 +657,7 @@ private boolean isReservedByOthersDuring(ExamMachine machine, Interval interval, } private static List getReservationsDuring(Collection reservations, Interval interval) { - return reservations.stream().filter(r -> interval.overlaps(r.toInterval())).collect(Collectors.toList()); + return reservations.stream().filter(r -> interval.overlaps(r.toInterval())).toList(); } private static DateTime nextStartingTime(DateTime instant, List startingHours, int offset) { diff --git a/app/impl/EmailComposerImpl.java b/app/impl/EmailComposerImpl.java index 32128f053b..3c1357c50f 100644 --- a/app/impl/EmailComposerImpl.java +++ b/app/impl/EmailComposerImpl.java @@ -21,7 +21,7 @@ import biweekly.component.VEvent; import biweekly.property.Summary; import com.google.common.collect.Sets; -import io.ebean.Ebean; +import io.ebean.DB; import io.vavr.Tuple2; import java.io.File; import java.io.FileOutputStream; @@ -61,8 +61,9 @@ import org.joda.time.DateTimeZone; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.Environment; -import play.Logger; import play.i18n.Lang; import play.i18n.MessagesApi; import util.config.ByodConfigHandler; @@ -78,7 +79,7 @@ class EmailComposerImpl implements EmailComposer { private static final DateTimeFormatter TF = DateTimeFormat.forPattern("HH:mm"); private static final int MINUTES_IN_HOUR = 60; - private static final Logger.ALogger logger = Logger.of(EmailComposerImpl.class); + private final Logger logger = LoggerFactory.getLogger(EmailComposerImpl.class); private final String hostName; private final DateTimeZone timeZone; @@ -234,7 +235,7 @@ public void composeWeeklySummary(User teacher) { // Nothing useful to send return; } - logger.info("Sending weekly report to: " + teacher.getEmail()); + logger.info("Sending weekly report to: {}", teacher.getEmail()); String templatePath = getTemplatesRoot() + "weeklySummary/weeklySummary.html"; String inspectionTemplatePath = getTemplatesRoot() + "weeklySummary/inspectionInfoSimple.html"; String template = fileHandler.read(templatePath); @@ -347,6 +348,10 @@ public void composeExaminationEventNotification(User recipient, ExamEnrolment en if (exam.getImplementation() == Exam.Implementation.CLIENT_AUTH) { // Attach a SEB config file + String quitPassword = byodConfigHandler.getPlaintextPassword( + config.getEncryptedQuitPassword(), + config.getQuitPasswordSalt() + ); String fileName = exam.getName().replace(" ", "-"); File file; try { @@ -355,7 +360,8 @@ public void composeExaminationEventNotification(User recipient, ExamEnrolment en byte[] data = byodConfigHandler.getExamConfig( config.getHash(), config.getEncryptedSettingsPassword(), - config.getSettingsPasswordSalt() + config.getSettingsPasswordSalt(), + quitPassword ); fos.write(data); fos.close(); @@ -543,7 +549,7 @@ private ICalendar createReservationEvent( String address, String... placeInfo ) { - List info = Stream.of(placeInfo).filter(s -> s != null && !s.isEmpty()).collect(Collectors.toList()); + List info = Stream.of(placeInfo).filter(s -> s != null && !s.isEmpty()).toList(); ICalendar iCal = new ICalendar(); iCal.setVersion(ICalVersion.V2_0); VEvent event = new VEvent(); @@ -574,7 +580,7 @@ public void composeExamReviewRequest(User toUser, User fromUser, Exam exam, Stri Map values = new HashMap<>(); - List exams = Ebean + List exams = DB .find(Exam.class) .where() .eq("parent.id", exam.getId()) @@ -830,29 +836,20 @@ public void composePrivateExamParticipantNotification(User student, User fromUse String.format("%s (%s)", exam.getName(), exam.getCourse().getCode().split("_")[0]) ); String teacherName = messaging.get(lang, "email.template.participant.notification.teacher", getTeachers(exam)); - DateTimeFormatter dtf = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm"); String events = exam .getExaminationEventConfigurations() .stream() - .map(c -> c.getExaminationEvent().getStart()) + .map(c -> new DateTime(c.getExaminationEvent().getStart(), timeZone)) .sorted() - .map(dtf::print) + .map(DTF::print) .collect(Collectors.joining(", ")); String examPeriod = isAquarium ? messaging.get( lang, "email.template.participant.notification.exam.period", - String.format( - "%s - %s", - DF.print(new DateTime(exam.getExamActiveStartDate())), - DF.print(new DateTime(exam.getExamActiveEndDate())) - ) + String.format("%s - %s", DF.print(exam.getPeriodStart()), DF.print(exam.getPeriodEnd())) ) - : messaging.get( - lang, - "email.template.participant.notification.exam.event", - String.format("%s (%s)", events, timeZone) - ); + : messaging.get(lang, "email.template.participant.notification.exam.event", events); String examDuration = messaging.get( lang, "email.template.participant.notification.exam.duration", @@ -1011,8 +1008,8 @@ public void composeCollaborativeExamAnnouncement(Set emails, User sender "email.template.participant.notification.exam.period", String.format( "%s - %s", - DF.print(new DateTime(exam.getExamActiveStartDate())), - DF.print(new DateTime(exam.getExamActiveEndDate())) + DF.print(new DateTime(exam.getPeriodStart())), + DF.print(new DateTime(exam.getPeriodEnd())) ) ); String examDuration = String.format( @@ -1051,13 +1048,13 @@ private List getEnrolments(Exam exam) { return false; }) .sorted() - .collect(Collectors.toList()); + .toList(); } private String createEnrolmentBlock(User teacher, Lang lang) { String enrolmentTemplatePath = getTemplatesRoot() + "weeklySummary/enrollmentInfo.html"; String enrolmentTemplate = fileHandler.read(enrolmentTemplatePath); - List exams = Ebean + List exams = DB .find(Exam.class) .fetch("course") .fetch("examEnrolments") @@ -1070,7 +1067,7 @@ private String createEnrolmentBlock(User teacher, Lang lang) { .endJunction() .isNotNull("course") .eq("state", Exam.State.PUBLISHED) - .gt("examActiveEndDate", new Date()) + .gt("periodEnd", new Date()) .findList(); return exams @@ -1091,7 +1088,7 @@ private String createEnrolmentBlock(User teacher, Lang lang) { noEnrolments ); } else { - ExamEnrolment first = t._2.get(0); + ExamEnrolment first = t._2.getFirst(); DateTime date = first.getReservation() != null ? adjustDST(first.getReservation().getStartAt()) : new DateTime( @@ -1111,7 +1108,7 @@ private String createEnrolmentBlock(User teacher, Lang lang) { // return exams in review state where teacher is either owner or inspector private static List getReviews(User teacher) { - return Ebean + return DB .find(ExamParticipation.class) .fetch("exam.course") .where() diff --git a/app/impl/EmailSenderImpl.java b/app/impl/EmailSenderImpl.java index b433c9c21c..87bd5300d2 100644 --- a/app/impl/EmailSenderImpl.java +++ b/app/impl/EmailSenderImpl.java @@ -24,11 +24,12 @@ import org.apache.commons.mail.EmailAttachment; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.HtmlEmail; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EmailSenderImpl implements EmailSender { - private static final Logger.ALogger logger = Logger.of(EmailSenderImpl.class); + private final Logger logger = LoggerFactory.getLogger(EmailSenderImpl.class); private final Config config; @Inject @@ -71,7 +72,7 @@ private void doSend( for (String r : recipients) { email.addTo(r); } - email.setFrom(String.format("Exam <%s>", config.getString("sitnet.email.system.account"))); + email.setFrom(String.format("Exam <%s>", config.getString("exam.email.system.account"))); email.addReplyTo(sender); for (String addr : cc) { email.addCc(addr); diff --git a/app/impl/ExamUpdaterImpl.java b/app/impl/ExamUpdaterImpl.java index 17dd395800..68f2d59419 100644 --- a/app/impl/ExamUpdaterImpl.java +++ b/app/impl/ExamUpdaterImpl.java @@ -3,8 +3,7 @@ import static play.mvc.Results.badRequest; import static play.mvc.Results.forbidden; -import akka.actor.ActorSystem; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -32,8 +31,10 @@ import models.questions.ClozeTestAnswer; import models.questions.Question; import models.sections.ExamSection; +import org.apache.pekko.actor.ActorSystem; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Http; import play.mvc.Result; import sanitizers.Attrs; @@ -51,7 +52,7 @@ public class ExamUpdaterImpl implements ExamUpdater { @Inject private ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(ExamUpdaterImpl.class); + private final Logger logger = LoggerFactory.getLogger(ExamUpdaterImpl.class); @Override public Optional updateTemporalFieldsAndValidate(Exam exam, User user, Http.Request request) { @@ -64,27 +65,37 @@ public Optional updateTemporalFieldsAndValidate(Exam exam, User user, Ht exam.setDuration(newDuration.orElse(null)); return Optional.empty(); } + if (exam.isUnsupervised() && newEnd.isPresent()) { + Set dates = exam + .getExaminationEventConfigurations() + .stream() + .map(c -> c.getExaminationEvent().getStart()) + .collect(Collectors.toSet()); + if (dates.stream().anyMatch(d -> d.isAfter(newEnd.get()))) { + return Optional.of(forbidden("i18n_error_future_reservations_exist")); + } + } boolean hasFutureReservations = hasFutureReservations(exam); boolean isAdmin = user.hasRole(Role.Name.ADMIN); if (newStart.isPresent()) { if (isAdmin || !hasFutureReservations || isNonRestrictingValidityChange(newStart.get(), exam, true)) { - exam.setExamActiveStartDate(newStart.get()); + exam.setPeriodStart(newStart.get()); } else { - return Optional.of(forbidden("sitnet_error_future_reservations_exist")); + return Optional.of(forbidden("i18n_error_future_reservations_exist")); } } if (newEnd.isPresent()) { if (isAdmin || !hasFutureReservations || isNonRestrictingValidityChange(newEnd.get(), exam, false)) { - exam.setExamActiveEndDate(newEnd.get()); + exam.setPeriodEnd(newEnd.get()); } else { - return Optional.of(forbidden("sitnet_error_future_reservations_exist")); + return Optional.of(forbidden("i18n_error_future_reservations_exist")); } } if (newDuration.isPresent()) { if (Objects.equals(newDuration.get(), exam.getDuration()) || !hasFutureReservations || isAdmin) { exam.setDuration(newDuration.get()); } else { - return Optional.of(forbidden("sitnet_error_future_reservations_exist")); + return Optional.of(forbidden("i18n_error_future_reservations_exist")); } } return Optional.empty(); @@ -114,7 +125,7 @@ public Optional updateStateAndValidate(Exam exam, User user, Http.Reques } // no sections named if (exam.getExamSections().stream().anyMatch(section -> section.getName() == null)) { - return Optional.of(badRequest("sitnet_exam_contains_unnamed_sections")); + return Optional.of(badRequest("i18n_exam_contains_unnamed_sections")); } if (exam.getExamLanguages().isEmpty()) { return Optional.of(badRequest("no exam languages specified")); @@ -136,7 +147,7 @@ public Optional updateStateAndValidate(Exam exam, User user, Http.Reques if (exam.isPrivate() && exam.getState() != Exam.State.PUBLISHED) { // No participants added, this is not good. if (exam.getExamEnrolments().isEmpty()) { - return Optional.of(badRequest("sitnet_no_participants")); + return Optional.of(badRequest("i18n_no_participants")); } notifyParticipantsAboutPrivateExamPublication(exam, user); } @@ -160,7 +171,6 @@ public void update(Exam exam, Http.Request request, Role.Name loginRole) { Optional examType = request.attrs().getOptional(Attrs.TYPE); Optional organisations = request.attrs().getOptional(Attrs.ORGANISATIONS); Integer trialCount = request.attrs().getOptional(Attrs.TRIAL_COUNT).orElse(null); - Boolean expanded = request.attrs().getOptional(Attrs.EXPANDED).orElse(false); Boolean requiresLanguageInspection = request.attrs().getOptional(Attrs.LANG_INSPECTION_REQUIRED).orElse(null); String internalRef = request.attrs().getOptional(Attrs.REFERENCE).orElse(null); Boolean anonymous = request.attrs().getOptional(Attrs.ANONYMOUS).orElse(false); @@ -187,14 +197,13 @@ public void update(Exam exam, Http.Request request, Role.Name loginRole) { } } examType.ifPresent(type -> { - ExamType eType = Ebean.find(ExamType.class).where().eq("type", type).findOne(); + ExamType eType = DB.find(ExamType.class).where().eq("type", type).findOne(); if (eType != null) { exam.setExamType(eType); } }); exam.setTrialCount(trialCount); - exam.setExpanded(expanded); exam.setSubjectToLanguageInspection(requiresLanguageInspection); exam.setInternalRef(internalRef); if (impl == Exam.Implementation.WHATEVER && configReader.isHomeExaminationSupported()) { @@ -297,9 +306,9 @@ public void updateAutoEvaluationConfig(Exam exam, AutoEvaluationConfig newConfig @Override public Optional updateLanguage(Exam exam, String code, User user) { if (!isPermittedToUpdate(exam, user)) { - return Optional.of(forbidden("sitnet_error_access_forbidden")); + return Optional.of(forbidden("i18n_error_access_forbidden")); } - Language language = Ebean.find(Language.class, code); + Language language = DB.find(Language.class, code); if (exam.getExamLanguages().contains(language)) { exam.getExamLanguages().remove(language); } else { @@ -335,7 +344,7 @@ private void updateGradeEvaluations(Exam exam, AutoEvaluationConfig newConfig) { GradeScale gs = exam.getGradeScale() == null ? exam.getCourse().getGradeScale() : exam.getGradeScale(); // Handle proposed entries, persist new ones where necessary for (GradeEvaluation src : newConfig.getGradeEvaluations()) { - Grade grade = Ebean.find(Grade.class, src.getGrade().getId()); + Grade grade = DB.find(Grade.class, src.getGrade().getId()); if (grade != null && gs.getGrades().contains(grade)) { GradeEvaluation ge = gradeMap.get(grade.getId()); if (ge == null) { @@ -386,20 +395,20 @@ private Optional getFormValidationError(boolean checkPeriod, Http.Reques Optional start = request.attrs().getOptional(Attrs.START_DATE); Optional end = request.attrs().getOptional(Attrs.END_DATE); if (start.isEmpty()) { - reason = "sitnet_error_start_date"; + reason = "i18n_error_start_date"; } else if (end.isEmpty()) { - reason = "sitnet_error_end_date"; + reason = "i18n_error_end_date"; } else if (start.get().isAfter(end.get())) { - reason = "sitnet_error_end_sooner_than_start"; + reason = "i18n_error_end_sooner_than_start"; }/*else if (end.get().isBeforeNow()) { // CSCEXAM-1127 - reason = "sitnet_error_end_sooner_than_now"; + reason = "i18n_error_end_sooner_than_now"; }*/ } return reason == null ? Optional.empty() : Optional.of(badRequest(reason)); } private boolean isNonRestrictingValidityChange(DateTime newDate, Exam exam, boolean isStartDate) { - DateTime oldDate = isStartDate ? exam.getExamActiveStartDate() : exam.getExamActiveEndDate(); + DateTime oldDate = isStartDate ? exam.getPeriodStart() : exam.getPeriodEnd(); return isStartDate ? !oldDate.isBefore(newDate) : !newDate.isBefore(oldDate); } @@ -407,7 +416,7 @@ private void updateGrading(Exam exam, int grading) { // Allow updating grading if allowed in settings or if course does not restrict the setting boolean canOverrideGrading = configReader.isCourseGradeScaleOverridable(); if (canOverrideGrading || exam.getCourse() == null || exam.getCourse().getGradeScale() == null) { - GradeScale scale = Ebean.find(GradeScale.class).fetch("grades").where().idEq(grading).findOne(); + GradeScale scale = DB.find(GradeScale.class).fetch("grades").where().idEq(grading).findOne(); if (scale != null) { exam.setGradeScale(scale); } else { diff --git a/app/impl/ExternalCourseHandlerImpl.java b/app/impl/ExternalCourseHandlerImpl.java index 7aa06f5133..ec9b7e7034 100644 --- a/app/impl/ExternalCourseHandlerImpl.java +++ b/app/impl/ExternalCourseHandlerImpl.java @@ -15,15 +15,17 @@ package impl; -import akka.util.ByteString; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -49,9 +51,11 @@ import models.GradeScale; import models.Organisation; import models.User; +import org.apache.pekko.util.ByteString; import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; -import play.Logger; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; @@ -66,7 +70,7 @@ public class ExternalCourseHandlerImpl implements ExternalCourseHandler { private static final DateFormat DF = new SimpleDateFormat("yyyyMMdd"); private static final ByteString BOM = ByteString.fromArray(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }); - private static final Logger.ALogger logger = Logger.of(ExternalCourseHandlerImpl.class); + private final Logger logger = LoggerFactory.getLogger(ExternalCourseHandlerImpl.class); private static class RemoteException extends Exception { @@ -99,7 +103,7 @@ public ExternalCourseHandlerImpl(WSClient wsClient, ConfigReader configReader) { } private Set getLocalCourses(String code) { - return Ebean + return DB .find(Course.class) .where() .ilike("code", code + "%") @@ -157,14 +161,14 @@ public CompletionStage> getPermittedCourses(User user) throws .collect(Collectors.toSet()); } else { logger.warn("Unexpected content {}", root.asText()); - throw new RemoteException("sitnet_request_timed_out"); + throw new RemoteException("i18n_request_timed_out"); } }; return request.get().thenApplyAsync(onSuccess); } private void saveOrUpdate(Course external) { - Ebean + DB .find(Course.class) .where() .eq("code", external.getCode()) @@ -212,7 +216,7 @@ private CompletionStage> downloadCourses(URL url) { return parseCourses(stripBom(response)); } logger.info("Non-OK response received for URL: {}. Status: {}", url, status); - throw new RemoteException(String.format("sitnet_remote_failure %d %s", status, response.getStatusText())); + throw new RemoteException(String.format("i18n_remote_failure %d %s", status, response.getStatusText())); }; return request .get() @@ -224,7 +228,7 @@ private CompletionStage> downloadCourses(URL url) { } private URL parseUrl(Organisation organisation, String courseCode) throws MalformedURLException { - String urlConfigPrefix = "sitnet.integration.courseUnitInfo.url"; + String urlConfigPrefix = "exam.integration.courseUnitInfo.url"; String configPath = null; if (organisation != null && organisation.getCode() != null) { String path = String.format("%s.%s", urlConfigPrefix, organisation.getCode()); @@ -237,37 +241,40 @@ private URL parseUrl(Organisation organisation, String courseCode) throws Malfor if (configReader.hasPath(path)) { configPath = path; } else { - throw new RuntimeException("sitnet.integration.courseUnitInfo.url holds no suitable URL for user"); + throw new RuntimeException("exam.integration.courseUnitInfo.url holds no suitable URL for user"); } } String url = configReader.getString(configPath); if (url == null || !url.contains(COURSE_CODE_PLACEHOLDER)) { - throw new RuntimeException("sitnet.integration.courseUnitInfo.url is malformed"); + throw new RuntimeException("exam.integration.courseUnitInfo.url is malformed"); } url = url.replace(COURSE_CODE_PLACEHOLDER, courseCode); - return new URL(url); + return URI.create(url).toURL(); } private URL parseUrl(User user) throws MalformedURLException { if ( configReader.getPermissionCheckUserIdentifier().equals("userIdentifier") && user.getUserIdentifier() == null ) { - throw new MalformedURLException("User has no identier number!"); + throw new MalformedURLException("User has no identifier number!"); } String url = configReader.getPermissionCheckUrl(); if (url == null || !url.contains(USER_ID_PLACEHOLDER)) { - throw new MalformedURLException("sitnet.integration.enrolmentPermissionCheck.url is malformed"); + throw new MalformedURLException("exam.integration.enrolmentPermissionCheck.url is malformed"); } - String identifier = configReader.getPermissionCheckUserIdentifier().equals("userIdentifier") - ? user.getUserIdentifier() - : user.getEppn(); + String identifier = URLEncoder.encode( + configReader.getPermissionCheckUserIdentifier().equals("userIdentifier") + ? user.getUserIdentifier() + : user.getEppn(), + StandardCharsets.UTF_8 + ); url = url.replace(USER_ID_PLACEHOLDER, identifier).replace(USER_LANG_PLACEHOLDER, user.getLanguage().getCode()); - return new URL(url); + return URI.create(url).toURL(); } private Optional importScale(JsonNode node) { String externalRef = node.get("code").asText(); - Optional ogs = Ebean.find(GradeScale.class).where().eq("externalRef", externalRef).findOneOrEmpty(); + Optional ogs = DB.find(GradeScale.class).where().eq("externalRef", externalRef).findOneOrEmpty(); if (ogs.isPresent()) { return ogs; } @@ -275,7 +282,7 @@ private Optional importScale(JsonNode node) { gs.setDescription(GradeScale.Type.OTHER.toString()); gs.setExternalRef(externalRef); gs.setDisplayName(node.get("name").asText()); - logger.info("saving scale " + externalRef); + logger.info("saving scale {}", externalRef); gs.save(); Stream gradesNode = StreamSupport .stream(node.get("grades").spliterator(), false) @@ -327,8 +334,8 @@ private List getGradeScales(JsonNode src) { Optional gst = GradeScale.Type.get(type); return gst.isPresent() && gst.get() != GradeScale.Type.OTHER; }) - .map(n -> Ebean.find(GradeScale.class).where().eq("type", n.get("type").asText()).findOne()); - return Stream.concat(externals, locals).collect(Collectors.toList()); + .map(n -> DB.find(GradeScale.class).where().eq("type", n.get("type").asText()).findOne()); + return Stream.concat(externals, locals).toList(); } return Collections.emptyList(); } @@ -377,7 +384,7 @@ private Optional parseCourse(JsonNode node) throws ParseException { } String name = node.get("institutionName").asText(); // TODO: how to identify (external) organisations. Maybe we need some "externalRef" for organisations as well? - Organisation organisation = Ebean.find(Organisation.class).where().ieq("name", name).findOne(); + Organisation organisation = DB.find(Organisation.class).where().ieq("name", name).findOne(); // TODO: should organisations preexist or not? As a safeguard, lets create these for now if not found. if (organisation == null) { organisation = new Organisation(); @@ -388,7 +395,7 @@ private Optional parseCourse(JsonNode node) throws ParseException { List scales = getGradeScales(node); if (!scales.isEmpty()) { // For now support just a single scale per course - course.setGradeScale(scales.get(0)); + course.setGradeScale(scales.getFirst()); } // in array form course.setCampus(getFirstName(node, "campus")); diff --git a/app/impl/NoShowHandlerImpl.java b/app/impl/NoShowHandlerImpl.java index 199e8c23ba..cdb72953c4 100644 --- a/app/impl/NoShowHandlerImpl.java +++ b/app/impl/NoShowHandlerImpl.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.List; import java.util.function.Function; @@ -27,7 +28,8 @@ import models.ExamInspection; import models.ExaminationEventConfiguration; import models.Reservation; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.Json; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; @@ -43,7 +45,7 @@ public class NoShowHandlerImpl implements NoShowHandler { private final ConfigReader configReader; - private static final Logger.ALogger logger = Logger.of(NoShowHandlerImpl.class); + private final Logger logger = LoggerFactory.getLogger(NoShowHandlerImpl.class); @Inject public NoShowHandlerImpl(EmailComposer composer, WSClient wsClient, ConfigReader configReader) { @@ -86,7 +88,9 @@ private void send(Reservation reservation) throws MalformedURLException { } private URL parseUrl(String reservationRef) throws MalformedURLException { - return new URL(configReader.getIopHost() + String.format("/api/enrolments/%s/noshow", reservationRef)); + return URI + .create(configReader.getIopHost() + String.format("/api/enrolments/%s/noshow", reservationRef)) + .toURL(); } private boolean isLocal(ExamEnrolment ee) { @@ -111,7 +115,6 @@ public void handleNoShows(List noShows, List reserva .filter(this::isNoShow) .filter(ns -> isLocal(ns) || isCollaborative(ns)); locals.forEach(this::handleNoShowAndNotify); - Stream externals = noShows .stream() .filter(ns -> @@ -161,10 +164,9 @@ public void handleNoShowAndNotify(ExamEnrolment enrolment) { enrolment.setNoShow(true); } enrolment.update(); - logger.info("Marked enrolment {} as no-show", enrolment.getId()); String examName = exam == null ? enrolment.getCollaborativeExam().getName() : enrolment.getExam().getName(); - String courseCode = exam == null ? "" : enrolment.getExam().getCourse().getCode(); + String courseCode = (exam == null || exam.getCourse() == null) ? "" : enrolment.getExam().getCourse().getCode(); // Notify student composer.composeNoShowMessage(enrolment.getUser(), examName, courseCode); diff --git a/app/models/Accessibility.java b/app/models/Accessibility.java index b1950ddf6a..a79773b30c 100644 --- a/app/models/Accessibility.java +++ b/app/models/Accessibility.java @@ -16,10 +16,10 @@ package models; import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToMany; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.ManyToMany; import models.base.GeneratedIdentityModel; @Entity diff --git a/app/models/Attachment.java b/app/models/Attachment.java index b3bb9cf96f..47f07fd0d7 100644 --- a/app/models/Attachment.java +++ b/app/models/Attachment.java @@ -15,8 +15,8 @@ package models; -import javax.persistence.Entity; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.Transient; import models.base.OwnedModel; @Entity diff --git a/app/models/AutoEvaluationConfig.java b/app/models/AutoEvaluationConfig.java index ee35e689c5..a431128f0b 100644 --- a/app/models/AutoEvaluationConfig.java +++ b/app/models/AutoEvaluationConfig.java @@ -17,18 +17,17 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import io.ebean.annotation.EnumValue; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import java.util.Date; import java.util.Map; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -104,12 +103,10 @@ public void setGradeEvaluations(Set gradeEvaluations) { this.gradeEvaluations = gradeEvaluations; } - @Transient public Map asGradeMap() { return gradeEvaluations.stream().collect(Collectors.toMap(ge -> ge.getGrade().getId(), Function.identity())); } - @Transient public AutoEvaluationConfig copy() { AutoEvaluationConfig clone = new AutoEvaluationConfig(); BeanUtils.copyProperties(this, clone, "id", "exam", "gradeEvaluations"); @@ -122,10 +119,9 @@ public AutoEvaluationConfig copy() { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof AutoEvaluationConfig)) { + if (!(other instanceof AutoEvaluationConfig otherEvaluation)) { return false; } - AutoEvaluationConfig otherEvaluation = (AutoEvaluationConfig) other; return new EqualsBuilder().append(id, otherEvaluation.id).build(); } diff --git a/app/models/Comment.java b/app/models/Comment.java index 2ed6c58390..2724ed70a0 100644 --- a/app/models/Comment.java +++ b/app/models/Comment.java @@ -15,10 +15,10 @@ package models; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.OneToOne; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; import models.api.AttachmentContainer; import models.base.OwnedModel; @@ -28,7 +28,6 @@ public class Comment extends OwnedModel implements AttachmentContainer { @Column(columnDefinition = "TEXT") private String comment; - @Column(columnDefinition = "BOOLEAN") private Boolean feedbackStatus; @OneToOne(cascade = CascadeType.ALL) diff --git a/app/models/Course.java b/app/models/Course.java index 8a8198b8a7..d7b813b35f 100644 --- a/app/models/Course.java +++ b/app/models/Course.java @@ -16,12 +16,12 @@ package models; import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import java.util.Date; import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -238,9 +238,7 @@ public void setOrganisation(Organisation organisation) { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Course)) return false; - - Course course = (Course) o; + if (!(o instanceof Course course)) return false; return new EqualsBuilder().append(code, course.code).isEquals(); } diff --git a/app/models/Exam.java b/app/models/Exam.java index 5c458e73fa..cb02307fa0 100644 --- a/app/models/Exam.java +++ b/app/models/Exam.java @@ -19,6 +19,18 @@ import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.ebean.annotation.EnumValue; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import jakarta.persistence.Transient; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; @@ -33,18 +45,6 @@ import java.util.TreeSet; import java.util.stream.Collectors; import javax.annotation.Nonnull; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; import models.api.AttachmentContainer; import models.base.OwnedModel; import models.questions.Question; @@ -181,12 +181,14 @@ public enum Implementation { // Exam valid/enrollable from @Temporal(TemporalType.TIMESTAMP) @JsonSerialize(using = DateTimeAdapter.class) - private DateTime examActiveStartDate; + @Column(name = "exam_active_start_date") + private DateTime periodStart; // Exam valid/enrollable until @Temporal(TemporalType.TIMESTAMP) @JsonSerialize(using = DateTimeAdapter.class) - private DateTime examActiveEndDate; + @Column(name = "exam_active_end_date") + private DateTime periodEnd; // Exam duration (minutes) private Integer duration; @@ -239,10 +241,6 @@ public enum Implementation { @OneToMany(mappedBy = "exam", cascade = CascadeType.ALL) private Set inspectionComments; - // In UI, section has been expanded - @Column(columnDefinition = "boolean default false") - private boolean expanded; - @OneToOne(cascade = CascadeType.ALL) private Attachment attachment; @@ -319,23 +317,21 @@ private double toFixed(double val) { } public Double getTotalScore() { - Double totalScore = toFixed( - examSections.stream().map(ExamSection::getTotalScore).reduce(0.0, (sum, x) -> sum += x) - ); + double totalScore = toFixed(examSections.stream().map(ExamSection::getTotalScore).reduce(0.0, Double::sum)); return Math.max(totalScore, 0.0); } public Double getMaxScore() { - return toFixed(examSections.stream().map(ExamSection::getMaxScore).reduce(0.0, (sum, x) -> sum += x)); + return toFixed(examSections.stream().map(ExamSection::getMaxScore).reduce(0.0, Double::sum)); } private int getApprovedAnswerCount() { - return examSections.stream().map(ExamSection::getApprovedCount).reduce(0, (sum, x) -> sum += x); + return examSections.stream().map(ExamSection::getApprovedCount).reduce(0, Integer::sum); } private int getRejectedAnswerCount() { - return examSections.stream().map(ExamSection::getRejectedCount).reduce(0, (sum, x) -> sum += x); + return examSections.stream().map(ExamSection::getRejectedCount).reduce(0, Integer::sum); } // These are dumb, required to be explicitly set by EBean @@ -387,14 +383,6 @@ public void setGradedTime(DateTime gradedTime) { this.gradedTime = gradedTime; } - public boolean getExpanded() { - return expanded; - } - - public void setExpanded(boolean expanded) { - this.expanded = expanded; - } - public String getName() { return name; } @@ -725,20 +713,20 @@ public Exam copy(User user) { return createCopy(user, false, true, Collections.emptySet()); } - public DateTime getExamActiveStartDate() { - return examActiveStartDate; + public DateTime getPeriodStart() { + return periodStart; } - public void setExamActiveStartDate(DateTime examActiveStartDate) { - this.examActiveStartDate = examActiveStartDate; + public void setPeriodStart(DateTime periodStart) { + this.periodStart = periodStart; } - public DateTime getExamActiveEndDate() { - return examActiveEndDate; + public DateTime getPeriodEnd() { + return periodEnd; } - public void setExamActiveEndDate(DateTime examActiveEndDate) { - this.examActiveEndDate = examActiveEndDate; + public void setPeriodEnd(DateTime periodEnd) { + this.periodEnd = periodEnd; } public void setAttachment(Attachment attachment) { @@ -829,39 +817,32 @@ public void setImplementation(Implementation implementation) { this.implementation = implementation; } - @Transient private boolean isCreatedBy(User user) { return creator != null && creator.equals(user); } - @Transient private boolean isInspectedBy(User user, boolean applyToChildOnly) { Exam examToCheck = parent == null || applyToChildOnly ? this : parent; return examToCheck.examInspections.stream().anyMatch(ei -> ei.getUser().equals(user)); } - @Transient private boolean isOwnedBy(User user) { Exam examToCheck = parent == null ? this : parent; return examToCheck.examOwners.stream().anyMatch(owner -> owner.equals(user)); } - @Transient public boolean isOwnedOrCreatedBy(User user) { return isCreatedBy(user) || isOwnedBy(user); } - @Transient public boolean isInspectedOrCreatedOrOwnedBy(User user) { return isInspectedBy(user, false) || isOwnedBy(user) || isCreatedBy(user); } - @Transient public boolean isChildInspectedOrCreatedOrOwnedBy(User user) { return isInspectedBy(user, true) || isOwnedBy(user) || isCreatedBy(user); } - @Transient public boolean isViewableForLanguageInspector(User user) { return ( executionType.getType().equals(ExamExecutionType.Type.MATURITY.toString()) && @@ -871,22 +852,22 @@ public boolean isViewableForLanguageInspector(User user) { ); } - @Transient public boolean isPrivate() { return !executionType.getType().equals(ExamExecutionType.Type.PUBLIC.toString()) && !isPrintout(); } - @Transient public boolean isPrintout() { return executionType.getType().equals(ExamExecutionType.Type.PRINTOUT.toString()); } - @Transient + public boolean isUnsupervised() { + return !executionType.getType().equals(Implementation.AQUARIUM.toString()); + } + public boolean hasState(State... states) { return Arrays.asList(states).contains(state); } - @Transient public void setDerivedMaxScores() { examSections .stream() @@ -905,10 +886,9 @@ public void setDerivedMaxScores() { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof Exam)) { + if (!(other instanceof Exam otherExam)) { return false; } - Exam otherExam = (Exam) other; return new EqualsBuilder().append(id, otherExam.id).build(); } @@ -917,30 +897,6 @@ public int hashCode() { return new HashCodeBuilder().append(id).build(); } - @Override - public String toString() { - return ( - "Exam{" + - "course=" + - course + - ", id='" + - id + - '\'' + - ", name='" + - name + - '\'' + - ", examType=" + - examType + - ", hash='" + - hash + - '\'' + - ", state='" + - state + - '\'' + - '}' - ); - } - @Override public int compareTo(@Nonnull Exam other) { return created.compareTo(other.created); diff --git a/app/models/ExamEnrolment.java b/app/models/ExamEnrolment.java index df3c47ebfd..a6ceff7640 100644 --- a/app/models/ExamEnrolment.java +++ b/app/models/ExamEnrolment.java @@ -18,18 +18,18 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; +import java.util.Random; import java.util.Set; import javax.annotation.Nonnull; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import models.json.CollaborativeExam; import models.json.ExternalExam; @@ -42,6 +42,8 @@ @Entity public class ExamEnrolment extends GeneratedIdentityModel implements Comparable { + private static final int DELAY_MAX = 30; + @ManyToOne @JsonManagedReference private User user; @@ -86,6 +88,8 @@ public class ExamEnrolment extends GeneratedIdentityModel implements Comparable< private boolean retrialPermitted; + private int delay; + public User getUser() { return user; } @@ -190,11 +194,22 @@ public void setRetrialPermitted(boolean retrialPermitted) { this.retrialPermitted = retrialPermitted; } - @Transient + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } + public boolean isProcessed() { return (exam != null && exam.hasState(Exam.State.GRADED_LOGGED, Exam.State.ARCHIVED, Exam.State.DELETED)); } + public void setRandomDelay() { + this.setDelay(new Random().nextInt(DELAY_MAX)); + } + @Override public int compareTo(@Nonnull ExamEnrolment other) { if (reservation == null && other.reservation == null) { @@ -212,10 +227,9 @@ public int compareTo(@Nonnull ExamEnrolment other) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExamEnrolment)) { + if (!(other instanceof ExamEnrolment otherEnrolment)) { return false; } - ExamEnrolment otherEnrolment = (ExamEnrolment) other; return new EqualsBuilder().append(id, otherEnrolment.id).build(); } diff --git a/app/models/ExamExecutionType.java b/app/models/ExamExecutionType.java index e7412c5554..afb2f250fb 100644 --- a/app/models/ExamExecutionType.java +++ b/app/models/ExamExecutionType.java @@ -16,8 +16,8 @@ package models; import io.ebean.Model; -import javax.persistence.Entity; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; @Entity public class ExamExecutionType extends Model { diff --git a/app/models/ExamFeedbackConfig.java b/app/models/ExamFeedbackConfig.java index 129d7006f1..783ddec825 100644 --- a/app/models/ExamFeedbackConfig.java +++ b/app/models/ExamFeedbackConfig.java @@ -18,11 +18,10 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.ebean.annotation.EnumValue; -import javax.persistence.Entity; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -74,7 +73,6 @@ public void setReleaseDate(DateTime releaseDate) { this.releaseDate = releaseDate; } - @Transient public ExamFeedbackConfig copy() { ExamFeedbackConfig clone = new ExamFeedbackConfig(); BeanUtils.copyProperties(this, clone, "id", "exam"); @@ -84,10 +82,9 @@ public ExamFeedbackConfig copy() { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExamFeedbackConfig)) { + if (!(other instanceof ExamFeedbackConfig otherConfig)) { return false; } - ExamFeedbackConfig otherConfig = (ExamFeedbackConfig) other; return new EqualsBuilder().append(id, otherConfig.id).build(); } diff --git a/app/models/ExamInspection.java b/app/models/ExamInspection.java index 4dbd8c5329..55af7512ab 100644 --- a/app/models/ExamInspection.java +++ b/app/models/ExamInspection.java @@ -17,9 +17,9 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -87,10 +87,9 @@ public void setComment(Comment comment) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExamInspection)) { + if (!(other instanceof ExamInspection otherInspection)) { return false; } - ExamInspection otherInspection = (ExamInspection) other; return new EqualsBuilder().append(id, otherInspection.id).build(); } diff --git a/app/models/ExamMachine.java b/app/models/ExamMachine.java index 89c5807176..450e111a1e 100644 --- a/app/models/ExamMachine.java +++ b/app/models/ExamMachine.java @@ -17,14 +17,13 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import java.util.HashSet; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import org.joda.time.Interval; @@ -39,7 +38,6 @@ public class ExamMachine extends GeneratedIdentityModel { private String accessibilityInfo; // Checkbox indicating is there any accessibility issues concerning the room - @Column(columnDefinition = "boolean default false") @Deprecated private boolean accessible; @@ -66,7 +64,6 @@ public class ExamMachine extends GeneratedIdentityModel { private List reservations; // In UI, section has been expanded - @Column(columnDefinition = "boolean default false") private boolean expanded; // Machine may be out of service, @@ -196,12 +193,10 @@ public void setAccessibilities(List accessibilities) { this.accessibilities = accessibilities; } - @Transient public boolean hasRequiredSoftware(Exam exam) { - return softwareInfo.containsAll(exam.getSoftwareInfo()); + return new HashSet<>(softwareInfo).containsAll(exam.getSoftwareInfo()); } - @Transient public boolean isReservedDuring(Interval interval) { return reservations.stream().anyMatch(r -> interval.overlaps(r.toInterval())); } diff --git a/app/models/ExamParticipation.java b/app/models/ExamParticipation.java index 4016b1105f..0ddfcf552c 100644 --- a/app/models/ExamParticipation.java +++ b/app/models/ExamParticipation.java @@ -18,12 +18,12 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.base.GeneratedIdentityModel; import models.json.CollaborativeExam; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -156,10 +156,9 @@ public void setSentForReview(DateTime sentForReview) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExamParticipation)) { + if (!(other instanceof ExamParticipation otherParticipation)) { return false; } - ExamParticipation otherParticipation = (ExamParticipation) other; return new EqualsBuilder().append(id, otherParticipation.id).build(); } diff --git a/app/models/ExamRecord.java b/app/models/ExamRecord.java index 2a6f8c075c..43a1aee2d8 100644 --- a/app/models/ExamRecord.java +++ b/app/models/ExamRecord.java @@ -16,13 +16,15 @@ package models; import com.fasterxml.jackson.annotation.JsonManagedReference; -import java.util.Date; -import javax.persistence.Entity; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.base.GeneratedIdentityModel; import models.dto.ExamScore; +import org.joda.time.DateTime; +import util.datetime.DateTimeAdapter; @Entity public class ExamRecord extends GeneratedIdentityModel { @@ -40,9 +42,10 @@ public class ExamRecord extends GeneratedIdentityModel { @JsonManagedReference private ExamScore examScore; - // what timestamp is this? The moments teacher marked Exam as recorded + // The moment exam was marked as graded and logged @Temporal(TemporalType.TIMESTAMP) - private Date timeStamp; + @JsonSerialize(using = DateTimeAdapter.class) + private DateTime timeStamp; public User getTeacher() { return teacher; @@ -76,11 +79,11 @@ public void setExamScore(ExamScore examScore) { this.examScore = examScore; } - public Date getTimeStamp() { + public DateTime getTimeStamp() { return timeStamp; } - public void setTimeStamp(Date timeStamp) { + public void setTimeStamp(DateTime timeStamp) { this.timeStamp = timeStamp; } } diff --git a/app/models/ExamRoom.java b/app/models/ExamRoom.java index 475ffc4025..90933565ed 100644 --- a/app/models/ExamRoom.java +++ b/app/models/ExamRoom.java @@ -18,14 +18,14 @@ import com.fasterxml.jackson.annotation.JsonManagedReference; import controllers.RoomLike; import io.ebean.Finder; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.ManyToMany; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; import models.base.GeneratedIdentityModel; import models.calendar.DefaultWorkingHours; import models.calendar.ExceptionWorkingHours; @@ -69,7 +69,6 @@ public enum State { private List accessibilities; // Checkbox indicating is there any accessibility issues concerning the room - @Column(columnDefinition = "boolean default false") private boolean accessible; @Column(columnDefinition = "TEXT") @@ -87,7 +86,6 @@ public enum State { private String statusComment; - @Column(columnDefinition = "boolean default false") private boolean outOfService; private String state; @@ -97,7 +95,6 @@ public enum State { private List examMachines; // In UI, section has been expanded - @Column(columnDefinition = "boolean default false") private boolean expanded; private String localTimezone; @@ -284,8 +281,7 @@ public void setLocalTimezone(String localTimezone) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ExamRoom)) return false; - ExamRoom examRoom = (ExamRoom) o; + if (!(o instanceof ExamRoom examRoom)) return false; return new EqualsBuilder().append(id, examRoom.id).build(); } diff --git a/app/models/ExamStartingHour.java b/app/models/ExamStartingHour.java index 13777c7142..c4837d2c8e 100644 --- a/app/models/ExamStartingHour.java +++ b/app/models/ExamStartingHour.java @@ -17,12 +17,12 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import java.util.Date; import javax.annotation.Nonnull; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import models.base.GeneratedIdentityModel; import org.joda.time.LocalTime; diff --git a/app/models/ExamType.java b/app/models/ExamType.java index 07711f34cf..ab4234c962 100644 --- a/app/models/ExamType.java +++ b/app/models/ExamType.java @@ -15,8 +15,7 @@ package models; -import javax.persistence.Column; -import javax.persistence.Entity; +import jakarta.persistence.Entity; import models.base.GeneratedIdentityModel; @Entity @@ -24,8 +23,7 @@ public class ExamType extends GeneratedIdentityModel { private String type; - @Column(columnDefinition = "boolean default false") - private Boolean deprecated; + private boolean deprecated; public ExamType(String type) { this.type = type; @@ -43,7 +41,7 @@ public void setDeprecated(boolean deprecated) { this.deprecated = deprecated; } - public Boolean isDeprecated() { + public boolean isDeprecated() { return deprecated; } } diff --git a/app/models/ExaminationDate.java b/app/models/ExaminationDate.java index fb9f1f0c6f..c4ea2cde9a 100644 --- a/app/models/ExaminationDate.java +++ b/app/models/ExaminationDate.java @@ -16,11 +16,11 @@ package models; import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import java.util.Date; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -54,10 +54,9 @@ public void setExam(Exam exam) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExaminationDate)) { + if (!(other instanceof ExaminationDate otherException)) { return false; } - ExaminationDate otherException = (ExaminationDate) other; return new EqualsBuilder().append(id, otherException.id).build(); } diff --git a/app/models/ExaminationEvent.java b/app/models/ExaminationEvent.java index b75c207691..35e258fa09 100644 --- a/app/models/ExaminationEvent.java +++ b/app/models/ExaminationEvent.java @@ -15,11 +15,10 @@ package models; -import javax.persistence.Entity; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -71,7 +70,6 @@ public void setExaminationEventConfiguration(ExaminationEventConfiguration exami this.examinationEventConfiguration = examinationEventConfiguration; } - @Transient public Interval toInterval(Exam exam) { return new Interval(start, start.plusMinutes(exam.getDuration())); } @@ -79,10 +77,9 @@ public Interval toInterval(Exam exam) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExaminationEvent)) { + if (!(other instanceof ExaminationEvent otherException)) { return false; } - ExaminationEvent otherException = (ExaminationEvent) other; return new EqualsBuilder().append(id, otherException.id).build(); } diff --git a/app/models/ExaminationEventConfiguration.java b/app/models/ExaminationEventConfiguration.java index 6eeca7f8dd..3c3715124b 100644 --- a/app/models/ExaminationEventConfiguration.java +++ b/app/models/ExaminationEventConfiguration.java @@ -17,14 +17,14 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Transient; import java.util.Set; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -48,9 +48,16 @@ public class ExaminationEventConfiguration extends GeneratedIdentityModel { @JsonIgnore private byte[] encryptedSettingsPassword; + @Lob + @JsonIgnore + private byte[] encryptedQuitPassword; + @JsonIgnore private String settingsPasswordSalt; + @JsonIgnore + private String quitPasswordSalt; + @JsonIgnore private String configKey; @@ -60,6 +67,9 @@ public class ExaminationEventConfiguration extends GeneratedIdentityModel { @Transient private String settingsPassword; + @Transient + private String quitPassword; + public Exam getExam() { return exam; } @@ -92,10 +102,26 @@ public void setEncryptedSettingsPassword(byte[] encryptedSettingsPassword) { this.encryptedSettingsPassword = encryptedSettingsPassword; } + public byte[] getEncryptedQuitPassword() { + return encryptedQuitPassword; + } + + public void setEncryptedQuitPassword(byte[] encryptedQuitPassword) { + this.encryptedQuitPassword = encryptedQuitPassword; + } + public String getSettingsPasswordSalt() { return settingsPasswordSalt; } + public String getQuitPasswordSalt() { + return quitPasswordSalt; + } + + public void setQuitPasswordSalt(String quitPasswordSalt) { + this.quitPasswordSalt = quitPasswordSalt; + } + public void setSettingsPasswordSalt(String settingsPasswordSalt) { this.settingsPasswordSalt = settingsPasswordSalt; } @@ -124,13 +150,19 @@ public void setSettingsPassword(String settingsPassword) { this.settingsPassword = settingsPassword; } + public String getQuitPassword() { + return quitPassword; + } + + public void setQuitPassword(String quitPassword) { + this.quitPassword = quitPassword; + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ExaminationEventConfiguration)) return false; - - ExaminationEventConfiguration that = (ExaminationEventConfiguration) o; + if (!(o instanceof ExaminationEventConfiguration that)) return false; return new EqualsBuilder().append(exam, that.exam).append(examinationEvent, that.examinationEvent).isEquals(); } diff --git a/app/models/GeneralSettings.java b/app/models/GeneralSettings.java index 8a00e06385..b53b28e5bb 100644 --- a/app/models/GeneralSettings.java +++ b/app/models/GeneralSettings.java @@ -15,7 +15,7 @@ package models; -import javax.persistence.Entity; +import jakarta.persistence.Entity; import models.base.GeneratedIdentityModel; @Entity diff --git a/app/models/Grade.java b/app/models/Grade.java index 1eca3b427d..10952b0863 100644 --- a/app/models/Grade.java +++ b/app/models/Grade.java @@ -17,7 +17,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import io.ebean.Model; -import javax.persistence.*; +import jakarta.persistence.*; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -73,10 +73,9 @@ public void setGradeScale(GradeScale gradeScale) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof Grade)) { + if (!(other instanceof Grade otherGrade)) { return false; } - Grade otherGrade = (Grade) other; return new EqualsBuilder().append(id, otherGrade.id).build(); } diff --git a/app/models/GradeEvaluation.java b/app/models/GradeEvaluation.java index 754acdaafb..166b407768 100644 --- a/app/models/GradeEvaluation.java +++ b/app/models/GradeEvaluation.java @@ -16,9 +16,8 @@ package models; import com.fasterxml.jackson.annotation.JsonBackReference; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -60,7 +59,6 @@ public void setPercentage(Integer percentage) { this.percentage = percentage; } - @Transient public GradeEvaluation copy() { GradeEvaluation clone = new GradeEvaluation(); BeanUtils.copyProperties(this, clone, "id"); @@ -70,10 +68,9 @@ public GradeEvaluation copy() { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof GradeEvaluation)) { + if (!(other instanceof GradeEvaluation otherEvaluation)) { return false; } - GradeEvaluation otherEvaluation = (GradeEvaluation) other; return new EqualsBuilder().append(grade, otherEvaluation.grade).build(); } diff --git a/app/models/GradeScale.java b/app/models/GradeScale.java index 44d9bab619..9c921fd504 100644 --- a/app/models/GradeScale.java +++ b/app/models/GradeScale.java @@ -16,9 +16,9 @@ package models; import io.ebean.Model; +import jakarta.persistence.*; import java.util.Optional; import java.util.Set; -import javax.persistence.*; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -111,10 +111,9 @@ public void setGrades(Set grades) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof GradeScale)) { + if (!(other instanceof GradeScale otherScale)) { return false; } - GradeScale otherScale = (GradeScale) other; return new EqualsBuilder().append(id, otherScale.id).build(); } diff --git a/app/models/InspectionComment.java b/app/models/InspectionComment.java index 083325b728..1d425c0938 100644 --- a/app/models/InspectionComment.java +++ b/app/models/InspectionComment.java @@ -15,9 +15,9 @@ package models; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; import models.base.OwnedModel; @Entity diff --git a/app/models/Language.java b/app/models/Language.java index 8305696ab6..bbd3f65d79 100644 --- a/app/models/Language.java +++ b/app/models/Language.java @@ -15,8 +15,8 @@ package models; -import javax.persistence.Entity; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; import models.base.VersionedModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -48,8 +48,7 @@ public void setCode(String code) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Language)) return false; - Language language = (Language) o; + if (!(o instanceof Language language)) return false; return new EqualsBuilder().append(code, language.code).build(); } diff --git a/app/models/LanguageInspection.java b/app/models/LanguageInspection.java index 1d199b96fd..7bab3767f9 100644 --- a/app/models/LanguageInspection.java +++ b/app/models/LanguageInspection.java @@ -15,12 +15,12 @@ package models; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import java.util.Date; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import models.base.OwnedModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -97,9 +97,7 @@ public void setAssignee(User assignee) { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof LanguageInspection)) return false; - - LanguageInspection that = (LanguageInspection) o; + if (!(o instanceof LanguageInspection that)) return false; return new EqualsBuilder().append(id, that.id).isEquals(); } diff --git a/app/models/MailAddress.java b/app/models/MailAddress.java index b7f509ab83..e1ab6b4246 100644 --- a/app/models/MailAddress.java +++ b/app/models/MailAddress.java @@ -15,7 +15,7 @@ package models; -import javax.persistence.Entity; +import jakarta.persistence.Entity; import models.base.GeneratedIdentityModel; @Entity diff --git a/app/models/Organisation.java b/app/models/Organisation.java index ae62d27610..c3559d233b 100644 --- a/app/models/Organisation.java +++ b/app/models/Organisation.java @@ -16,11 +16,11 @@ package models; import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; import models.base.GeneratedIdentityModel; @Entity diff --git a/app/models/Permission.java b/app/models/Permission.java index 15b0c8b9e7..fe434a776f 100644 --- a/app/models/Permission.java +++ b/app/models/Permission.java @@ -15,11 +15,11 @@ package models; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.ebean.annotation.EnumValue; +import jakarta.persistence.Entity; import java.util.Objects; import java.util.Optional; -import javax.persistence.Entity; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; @Entity @@ -28,12 +28,14 @@ public class Permission extends GeneratedIdentityModel implements be.objectify.d public enum Type { @EnumValue("1") CAN_INSPECT_LANGUAGE, + @EnumValue("2") + CAN_CREATE_BYOD_EXAM, } private Type type; @Override - @Transient + @JsonIgnore public String getValue() { return type.toString(); } @@ -58,8 +60,7 @@ public static Optional withValue(String name) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Permission)) return false; - Permission permission = (Permission) o; + if (!(o instanceof Permission permission)) return false; return Objects.equals(type, permission.type); } diff --git a/app/models/Reservation.java b/app/models/Reservation.java index 177dda524a..321fbcebca 100644 --- a/app/models/Reservation.java +++ b/app/models/Reservation.java @@ -17,15 +17,14 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import javax.annotation.Nonnull; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import models.iop.ExternalReservation; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -150,7 +149,6 @@ public void setExternalUserRef(String externalUserRef) { this.externalUserRef = externalUserRef; } - @Transient public Interval toInterval() { return new Interval(startAt, endAt); } @@ -163,8 +161,7 @@ public int compareTo(@Nonnull Reservation o) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Reservation)) return false; - Reservation that = (Reservation) o; + if (!(o instanceof Reservation that)) return false; return new EqualsBuilder().append(id, that.id).isEquals(); } diff --git a/app/models/Role.java b/app/models/Role.java index cb1c81cde7..503a4bfc83 100644 --- a/app/models/Role.java +++ b/app/models/Role.java @@ -15,8 +15,8 @@ package models; +import jakarta.persistence.Entity; import java.util.Objects; -import javax.persistence.Entity; import models.base.GeneratedIdentityModel; @Entity @@ -48,8 +48,7 @@ public static Role withName(String name) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Role)) return false; - Role role = (Role) o; + if (!(o instanceof Role role)) return false; return Objects.equals(name, role.name); } diff --git a/app/models/Software.java b/app/models/Software.java index dab596bd6a..9a302bf417 100644 --- a/app/models/Software.java +++ b/app/models/Software.java @@ -16,10 +16,11 @@ package models; import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToMany; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.ManyToMany; +import java.util.Objects; import models.base.GeneratedIdentityModel; @Entity @@ -62,11 +63,8 @@ public void setMachines(List machines) { @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Software software = (Software) o; - - return !(name != null ? !name.equals(software.name) : software.name != null); + if (!(o instanceof Software software)) return false; + return Objects.equals(name, software.name); } @Override diff --git a/app/models/Tag.java b/app/models/Tag.java index e020806078..37c2bd3e17 100644 --- a/app/models/Tag.java +++ b/app/models/Tag.java @@ -15,9 +15,13 @@ package models; -import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import java.util.List; -import javax.persistence.*; import models.base.OwnedModel; import models.questions.Question; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -31,7 +35,6 @@ public class Tag extends OwnedModel { private String name; @ManyToMany(mappedBy = "tags", cascade = CascadeType.ALL) - @JsonBackReference private List questions; public String getName() { @@ -53,10 +56,9 @@ public void setQuestions(List questions) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof Tag)) { + if (!(other instanceof Tag otherTag)) { return false; } - Tag otherTag = (Tag) other; return new EqualsBuilder().append(name, otherTag.name).build(); } diff --git a/app/models/User.java b/app/models/User.java index e6863b6976..2cb791cd70 100644 --- a/app/models/User.java +++ b/app/models/User.java @@ -18,18 +18,16 @@ import be.objectify.deadbolt.java.models.Subject; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import java.util.Date; import java.util.List; -import java.util.stream.Collectors; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -92,7 +90,6 @@ public void setUserAgreementAccepted(boolean userAgreementAccepted) { this.userAgreementAccepted = userAgreementAccepted; } - @Column(columnDefinition = "BOOLEAN DEFAULT FALSE") private boolean userAgreementAccepted; private Date lastLogin; @@ -237,7 +234,7 @@ public boolean hasRole(Role.Name name) { } public boolean hasPermission(Permission.Type type) { - return permissions.stream().map(Permission::getType).collect(Collectors.toList()).contains(type); + return permissions.stream().map(Permission::getType).toList().contains(type); } public Role.Name getLoginRole() { @@ -268,8 +265,7 @@ public String toString() { @Override public boolean equals(Object other) { if (other == this) return true; - if (!(other instanceof User)) return false; - User otherUser = (User) other; + if (!(other instanceof User otherUser)) return false; return new EqualsBuilder().append(getId(), otherUser.getId()).build(); } diff --git a/app/models/api/AttachmentContainer.java b/app/models/api/AttachmentContainer.java index 1ac2be3859..419ddb88e6 100644 --- a/app/models/api/AttachmentContainer.java +++ b/app/models/api/AttachmentContainer.java @@ -19,8 +19,6 @@ public interface AttachmentContainer { Attachment getAttachment(); - void setAttachment(Attachment attachment); - void save(); } diff --git a/app/models/base/GeneratedIdentityModel.java b/app/models/base/GeneratedIdentityModel.java index 347e38e7db..2b639d0529 100644 --- a/app/models/base/GeneratedIdentityModel.java +++ b/app/models/base/GeneratedIdentityModel.java @@ -15,10 +15,10 @@ package models.base; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; @MappedSuperclass public abstract class GeneratedIdentityModel extends VersionedModel { diff --git a/app/models/base/OwnedModel.java b/app/models/base/OwnedModel.java index cd48db9929..490e09729e 100644 --- a/app/models/base/OwnedModel.java +++ b/app/models/base/OwnedModel.java @@ -16,12 +16,11 @@ package models.base; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.MappedSuperclass; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.User; import org.joda.time.DateTime; import util.datetime.DateTimeAdapter; @@ -77,13 +76,11 @@ public void setModifier(User modifier) { this.modifier = modifier; } - @Transient public void setCreatorWithDate(User user) { setCreator(user); setCreated(DateTime.now()); } - @Transient public void setModifierWithDate(User user) { setModifier(user); setModified(DateTime.now()); diff --git a/app/models/base/VersionedModel.java b/app/models/base/VersionedModel.java index f658870826..260a4e47ac 100644 --- a/app/models/base/VersionedModel.java +++ b/app/models/base/VersionedModel.java @@ -16,8 +16,8 @@ package models.base; import io.ebean.Model; -import javax.persistence.MappedSuperclass; -import javax.persistence.Version; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Version; @MappedSuperclass public abstract class VersionedModel extends Model { diff --git a/app/models/calendar/DefaultWorkingHours.java b/app/models/calendar/DefaultWorkingHours.java index 554d360463..317b8a269c 100644 --- a/app/models/calendar/DefaultWorkingHours.java +++ b/app/models/calendar/DefaultWorkingHours.java @@ -17,11 +17,10 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.ExamRoom; import models.base.GeneratedIdentityModel; import org.joda.time.DateTime; @@ -88,7 +87,6 @@ public void setTimezoneOffset(int timezoneOffset) { this.timezoneOffset = timezoneOffset; } - @Transient public boolean overlaps(DefaultWorkingHours other) { return weekday.equals(other.weekday) && toInterval().overlaps(other.toInterval()); } diff --git a/app/models/calendar/ExceptionWorkingHours.java b/app/models/calendar/ExceptionWorkingHours.java index cb7cb8c046..2c7431f170 100644 --- a/app/models/calendar/ExceptionWorkingHours.java +++ b/app/models/calendar/ExceptionWorkingHours.java @@ -17,11 +17,11 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import java.util.Date; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import models.ExamRoom; import models.base.GeneratedIdentityModel; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -99,10 +99,9 @@ public void setOutOfService(boolean outOfService) { @Override public boolean equals(Object other) { if (this == other) return true; - if (!(other instanceof ExceptionWorkingHours)) { + if (!(other instanceof ExceptionWorkingHours otherException)) { return false; } - ExceptionWorkingHours otherException = (ExceptionWorkingHours) other; return new EqualsBuilder().append(id, otherException.id).build(); } diff --git a/app/models/calendar/MaintenancePeriod.java b/app/models/calendar/MaintenancePeriod.java index fa53004322..a80dd15b1d 100644 --- a/app/models/calendar/MaintenancePeriod.java +++ b/app/models/calendar/MaintenancePeriod.java @@ -1,9 +1,9 @@ package models.calendar; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import javax.persistence.Entity; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import jakarta.persistence.Entity; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import models.base.GeneratedIdentityModel; import org.joda.time.DateTime; import util.datetime.DateTimeAdapter; diff --git a/app/models/dto/ExamScore.java b/app/models/dto/ExamScore.java index 8057aaeadc..9b51111f23 100644 --- a/app/models/dto/ExamScore.java +++ b/app/models/dto/ExamScore.java @@ -19,11 +19,10 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.vavr.Tuple; import io.vavr.Tuple2; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; import java.util.ArrayList; import java.util.List; -import javax.persistence.Entity; -import javax.persistence.OneToOne; -import javax.persistence.Transient; import models.Exam; import models.ExamRecord; import models.User; @@ -241,7 +240,6 @@ public void setInstitutionName(String institutionName) { this.institutionName = institutionName; } - @Transient public static String[] getHeaders() { return new String[] { "id", @@ -273,7 +271,6 @@ public static String[] getHeaders() { }; } - @Transient public List> asCells(User student, User teacher, Exam exam) { List> cells = new ArrayList<>(); cells.add(Tuple.of(Long.toString(getId()), CellType.STRING)); @@ -305,7 +302,6 @@ public List> asCells(User student, User teacher, Exam e return cells; } - @Transient public String[] asArray(User student, User teacher, Exam exam) { return asCells(student, teacher, exam).stream().map(t -> t._1).toArray(String[]::new); } diff --git a/app/models/iop/ExternalReservation.java b/app/models/iop/ExternalReservation.java index 03059ecce4..a3cd9d1991 100644 --- a/app/models/iop/ExternalReservation.java +++ b/app/models/iop/ExternalReservation.java @@ -16,9 +16,9 @@ package models.iop; import controllers.RoomLike; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.OneToOne; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; import models.MailAddress; import models.base.GeneratedIdentityModel; diff --git a/app/models/json/CollaborativeExam.java b/app/models/json/CollaborativeExam.java index 32375c77eb..adb5214b5c 100644 --- a/app/models/json/CollaborativeExam.java +++ b/app/models/json/CollaborativeExam.java @@ -19,8 +19,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.persistence.*; import java.util.List; -import javax.persistence.*; import models.Exam; import models.ExamEnrolment; import models.ExamParticipation; @@ -47,15 +47,15 @@ public class CollaborativeExam extends GeneratedIdentityModel { @Column private Exam.State state; - @Column + @Column(name = "exam_active_start_date") @Temporal(TemporalType.TIMESTAMP) @JsonSerialize(using = DateTimeAdapter.class) - private DateTime examActiveStartDate; + private DateTime periodStart; - @Column + @Column(name = "exam_active_end_date") @Temporal(TemporalType.TIMESTAMP) @JsonSerialize(using = DateTimeAdapter.class) - private DateTime examActiveEndDate; + private DateTime periodEnd; @Column private Integer duration; @@ -101,20 +101,20 @@ public void setName(String name) { this.name = name; } - public DateTime getExamActiveStartDate() { - return examActiveStartDate; + public DateTime getPeriodStart() { + return periodStart; } - public void setExamActiveStartDate(DateTime examActiveStartDate) { - this.examActiveStartDate = examActiveStartDate; + public void setPeriodStart(DateTime periodStart) { + this.periodStart = periodStart; } - public DateTime getExamActiveEndDate() { - return examActiveEndDate; + public DateTime getPeriodEnd() { + return periodEnd; } - public void setExamActiveEndDate(DateTime examActiveEndDate) { - this.examActiveEndDate = examActiveEndDate; + public void setPeriodEnd(DateTime periodEnd) { + this.periodEnd = periodEnd; } public Integer getDuration() { @@ -181,7 +181,6 @@ public void setAnonymous(boolean anonymous) { this.anonymous = anonymous; } - @Transient public Exam getExam(JsonNode node) { final ObjectNode objectNode = (ObjectNode) node; objectNode.put("id", id).put("externalRef", externalRef); diff --git a/app/models/json/ExternalExam.java b/app/models/json/ExternalExam.java index 62506e2703..f21314ad3b 100644 --- a/app/models/json/ExternalExam.java +++ b/app/models/json/ExternalExam.java @@ -19,14 +19,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.ebean.annotation.DbJsonB; import io.ebean.text.json.EJson; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import java.io.IOException; import java.util.Map; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; import models.Exam; import models.User; import models.base.GeneratedIdentityModel; @@ -124,7 +123,6 @@ public void setContent(Map content) { this.content = content; } - @Transient public Exam deserialize() throws IOException { ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(content); @@ -132,7 +130,6 @@ public Exam deserialize() throws IOException { return JsonDeserializer.deserialize(Exam.class, node); } - @Transient public void serialize(Exam content) throws IOException { ObjectMapper om = new ObjectMapper(); String txt = om.writeValueAsString(content); diff --git a/app/models/questions/ClozeTestAnswer.java b/app/models/questions/ClozeTestAnswer.java index 767f1cd8e3..1c72207a5e 100644 --- a/app/models/questions/ClozeTestAnswer.java +++ b/app/models/questions/ClozeTestAnswer.java @@ -18,16 +18,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Transient; import java.lang.reflect.Type; import java.util.Collections; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.regex.Pattern; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Transient; import models.base.GeneratedIdentityModel; import models.sections.ExamSectionQuestion; import org.apache.commons.lang3.math.NumberUtils; @@ -53,9 +52,6 @@ public class ClozeTestAnswer extends GeneratedIdentityModel { @Transient private Score score; - @Transient - private List elements; - public String getAnswer() { return answer; } @@ -72,10 +68,6 @@ public Score getScore() { return score; } - public List getElements() { - return elements; - } - public ClozeTestAnswer copy() { ClozeTestAnswer clozeTestAnswer = new ClozeTestAnswer(); clozeTestAnswer.setAnswer(answer); @@ -100,11 +92,12 @@ public void setQuestion(ExamSectionQuestion esq) { b.text(""); b.attr("aria-label", "cloze test answer"); b.attr("type", isNumeric ? "number" : "text"); - b.attr("class", "cloze-input"); + b.attr("class", "cloze-input mt-2"); if (isNumeric) { b.attr("step", "any"); - // Should allow for using both comma and period as decimal separator - b.attr("lang", "en-150"); + // Hacky, but this should allow for using both comma and period as decimal separator even in Firefox + // regardless of browser language. + b.attr("lang", "fi"); } }); this.question = doc.body().children().toString(); @@ -200,7 +193,7 @@ private boolean isCorrectNumericAnswer(Element blank, String rawAnswer) { String precisionAttr = blank.attr("precision"); double answer = Double.parseDouble(answerText); Double correctAnswer = Double.parseDouble(blank.text().trim().replaceAll("(^\\h*)|(\\h*$)", "")); - Double precision = precisionAttr == null ? 0.0 : Double.parseDouble(precisionAttr); + Double precision = precisionAttr.isEmpty() ? 0.0 : Double.parseDouble(precisionAttr); return (correctAnswer - precision <= answer && answer <= correctAnswer + precision); } @@ -255,61 +248,4 @@ public int getIncorrectAnswers() { return incorrectAnswers; } } - - public abstract static class ContentElement { - - int order; - - ContentElement(int order) { - this.order = order; - } - - public int getOrder() { - return order; - } - - public abstract String getType(); - } - - public static class BlankElement extends ContentElement { - - boolean numeric; - String id; - - BlankElement(int order, boolean numeric, String id) { - super(order); - this.numeric = numeric; - this.id = id; - } - - public String getType() { - return "Blank"; - } - - public boolean isNumeric() { - return numeric; - } - - public String getId() { - return id; - } - } - - public static class TextElement extends ContentElement { - - String text; - - TextElement(int order, String text) { - super(order); - this.text = text; - } - - public String getType() { - return "Text"; - } - - public String getText() { - return text; - } - } } diff --git a/app/models/questions/EssayAnswer.java b/app/models/questions/EssayAnswer.java index 52d62b88af..16e9e1239b 100644 --- a/app/models/questions/EssayAnswer.java +++ b/app/models/questions/EssayAnswer.java @@ -15,11 +15,10 @@ package models.questions; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.OneToOne; -import javax.persistence.Transient; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; import models.Attachment; import models.api.AttachmentContainer; import models.base.OwnedModel; @@ -62,7 +61,6 @@ public void setEvaluatedScore(Double evaluatedScore) { this.evaluatedScore = evaluatedScore; } - @Transient public EssayAnswer copy() { EssayAnswer essayAnswer = new EssayAnswer(); essayAnswer.setAnswer(answer); diff --git a/app/models/questions/MultipleChoiceOption.java b/app/models/questions/MultipleChoiceOption.java index 95e165c8e1..c0073cad5a 100644 --- a/app/models/questions/MultipleChoiceOption.java +++ b/app/models/questions/MultipleChoiceOption.java @@ -17,11 +17,11 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import io.ebean.annotation.EnumValue; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import java.util.Set; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; import javax.validation.constraints.NotNull; import models.base.GeneratedIdentityModel; import models.sections.ExamSectionQuestionOption; diff --git a/app/models/questions/Question.java b/app/models/questions/Question.java index ef0149df03..de48484a36 100644 --- a/app/models/questions/Question.java +++ b/app/models/questions/Question.java @@ -20,6 +20,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import io.ebean.annotation.EnumValue; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import java.util.List; import java.util.Map; import java.util.Objects; @@ -27,16 +36,6 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.Transient; import models.Attachment; import models.Tag; import models.User; @@ -123,6 +122,11 @@ public enum EvaluationType { private List options; @ManyToMany(cascade = CascadeType.ALL) + @JoinTable( + name = "question_tag", + joinColumns = @JoinColumn(name = "question_id"), + inverseJoinColumns = @JoinColumn(name = "tag_id") + ) private List tags; @ManyToMany(cascade = CascadeType.ALL) @@ -263,12 +267,10 @@ public void setQuestionOwners(Set questionOwners) { this.questionOwners = questionOwners; } - @Transient private boolean nodeExists(JsonNode node, String name) { return node.get(name) != null && !node.get(name).isNull(); } - @Transient private String getClozeTestQuestionContentValidationResult(JsonNode node) { String reason = null; String questionText = node.get("question").asText(); @@ -297,7 +299,6 @@ private String getClozeTestQuestionContentValidationResult(JsonNode node) { return reason; } - @Transient private boolean getClaimChoiceOptionsValidationResult(ArrayNode options) { // Check that all required option conditions are met, discarding possible duplicates return ( @@ -315,21 +316,15 @@ private boolean getClaimChoiceOptionsValidationResult(ArrayNode options) { } return ( - ( - type == MultipleChoiceOption.ClaimChoiceOptionType.CorrectOption && + (type == MultipleChoiceOption.ClaimChoiceOptionType.CorrectOption && defaultScore > 0 && - !option.isEmpty() - ) || - ( - type == MultipleChoiceOption.ClaimChoiceOptionType.IncorrectOption && + !option.isEmpty()) || + (type == MultipleChoiceOption.ClaimChoiceOptionType.IncorrectOption && defaultScore <= 0 && - !option.isEmpty() - ) || - ( - type == MultipleChoiceOption.ClaimChoiceOptionType.SkipOption && + !option.isEmpty()) || + (type == MultipleChoiceOption.ClaimChoiceOptionType.SkipOption && defaultScore == 0 && - !option.isEmpty() - ) + !option.isEmpty()) ); }) .map(n -> @@ -345,12 +340,11 @@ private boolean getClaimChoiceOptionsValidationResult(ArrayNode options) { ); } - @Transient public Optional getValidationResult(JsonNode node) { String reason = null; if (nodeExists(node, "question")) { switch (type) { - case EssayQuestion: + case EssayQuestion -> { if (!nodeExists(node, "defaultEvaluationType")) { reason = "no evaluation type defined"; } @@ -358,26 +352,26 @@ public Optional getValidationResult(JsonNode node) { if (type == EvaluationType.Points && !nodeExists(node, "defaultMaxScore")) { reason = "no max score defined"; } - break; - case MultipleChoiceQuestion: + } + case MultipleChoiceQuestion -> { if (nodeExists(node, "options")) { ArrayNode an = (ArrayNode) node.get("options"); if (an.size() < 2) { - reason = "sitnet_minimum_of_two_options_required"; + reason = "i18n_minimum_of_two_options_required"; } else if ( StreamSupport .stream(an.spliterator(), false) .noneMatch(n -> n.get("correctOption").asBoolean()) ) { - reason = "sitnet_correct_option_required"; + reason = "i18n_correct_option_required"; } } else { - reason = "sitnet_minimum_of_two_options_required"; + reason = "i18n_minimum_of_two_options_required"; } - break; - case WeightedMultipleChoiceQuestion: + } + case WeightedMultipleChoiceQuestion -> { if (!nodeExists(node, "options") || node.get("options").size() < 2) { - reason = "sitnet_minimum_of_two_options_required"; + reason = "i18n_minimum_of_two_options_required"; } else { ArrayNode options = (ArrayNode) node.get("options"); if ( @@ -385,37 +379,35 @@ public Optional getValidationResult(JsonNode node) { .stream(options.spliterator(), false) .noneMatch(n -> n.get("defaultScore").asDouble() > 0) ) { - reason = "sitnet_correct_option_required"; + reason = "i18n_correct_option_required"; } } - break; - case ClozeTestQuestion: + } + case ClozeTestQuestion -> { if (!nodeExists(node, "defaultMaxScore")) { reason = "no max score defined"; } else { reason = getClozeTestQuestionContentValidationResult(node); } - break; - case ClaimChoiceQuestion: + } + case ClaimChoiceQuestion -> { if (!nodeExists(node, "options") || node.get("options").size() != 3) { - reason = "sitnet_three_answers_required_in_claim_question"; + reason = "i18n_three_answers_required_in_claim_question"; } else { ArrayNode options = (ArrayNode) node.get("options"); boolean hasValidOptions = getClaimChoiceOptionsValidationResult(options); if (!hasValidOptions) { - reason = "sitnet_incorrect_claim_question_options"; + reason = "i18n_incorrect_claim_question_options"; } } - break; - default: - reason = "unknown question type"; - break; + } + default -> reason = "unknown question type"; } } else { reason = "no question text defined"; } - if (!nodeExists(node, "questionOwners") || node.get("questionOwners").size() == 0) { + if (!nodeExists(node, "questionOwners") || node.get("questionOwners").isEmpty()) { reason = "no owners defined"; } if (reason != null) { @@ -424,36 +416,37 @@ public Optional getValidationResult(JsonNode node) { return Optional.empty(); } - @Transient public Double getMaxDefaultScore() { switch (getType()) { - case EssayQuestion: + case EssayQuestion -> { if (defaultEvaluationType == EvaluationType.Points) { return defaultMaxScore == null ? 0 : defaultMaxScore; } - break; - case MultipleChoiceQuestion: + } + case MultipleChoiceQuestion -> { return defaultMaxScore == null ? 0 : defaultMaxScore; - case WeightedMultipleChoiceQuestion: + } + case WeightedMultipleChoiceQuestion -> { return options .stream() .map(MultipleChoiceOption::getDefaultScore) .filter(score -> score != null && score > 0) - .reduce(0.0, (sum, x) -> sum += x); - case ClaimChoiceQuestion: + .reduce(0.0, Double::sum); + } + case ClaimChoiceQuestion -> { return options.stream().mapToDouble(MultipleChoiceOption::getDefaultScore).max().orElse(0.0); + } } return 0.0; } - @Transient public Double getMinDefaultScore() { if (getType() == Type.WeightedMultipleChoiceQuestion) { return options .stream() .map(MultipleChoiceOption::getDefaultScore) .filter(score -> score != null && score < 0) - .reduce(0.0, (sum, x) -> sum += x); + .reduce(0.0, Double::sum); } else if (getType() == Type.ClaimChoiceQuestion) { return options.stream().mapToDouble(MultipleChoiceOption::getDefaultScore).min().orElse(0.0); } @@ -465,10 +458,9 @@ public boolean equals(Object object) { if (this == object) { return true; } - if (!(object instanceof Question)) { + if (!(object instanceof Question other)) { return false; } - Question other = (Question) object; return new EqualsBuilder().append(id, other.getId()).build(); } diff --git a/app/models/sections/ExamMaterial.java b/app/models/sections/ExamMaterial.java index 97c896f7ae..471b4af15f 100644 --- a/app/models/sections/ExamMaterial.java +++ b/app/models/sections/ExamMaterial.java @@ -15,9 +15,9 @@ package models.sections; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToMany; import java.util.Set; -import javax.persistence.Entity; -import javax.persistence.ManyToMany; import models.User; import models.base.OwnedModel; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -70,9 +70,7 @@ public void setExamSections(Set examSections) { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ExamMaterial)) return false; - - ExamMaterial that = (ExamMaterial) o; + if (!(o instanceof ExamMaterial that)) return false; return new EqualsBuilder().append(id, that.id).isEquals(); } diff --git a/app/models/sections/ExamSection.java b/app/models/sections/ExamSection.java index b6245c8152..72211bfdcc 100644 --- a/app/models/sections/ExamSection.java +++ b/app/models/sections/ExamSection.java @@ -17,6 +17,13 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -24,15 +31,6 @@ import java.util.Objects; import java.util.Set; import javax.annotation.Nonnull; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Transient; import models.Exam; import models.ExamEnrolment; import models.User; @@ -58,13 +56,10 @@ public final class ExamSection extends OwnedModel implements Comparable sum += x); + .reduce(0.0, Double::sum); } - @Transient public double getMaxScore() { return sectionQuestions .stream() .map(ExamSectionQuestion::getMaxAssessedScore) .filter(Objects::nonNull) - .reduce(0.0, (sum, x) -> sum += x); + .reduce(0.0, Double::sum); } - @Transient public int getRejectedCount() { return (int) sectionQuestions.stream().filter(ExamSectionQuestion::isRejected).count(); } - @Transient public int getApprovedCount() { return (int) sectionQuestions.stream().filter(ExamSectionQuestion::isApproved).count(); } - @Transient public boolean hasQuestion(Question question) { return sectionQuestions.stream().map(ExamSectionQuestion::getQuestion).anyMatch(q -> q.equals(question)); } @@ -262,8 +252,7 @@ public void setOrdinal(Integer ordinal) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ExamSection)) return false; - ExamSection that = (ExamSection) o; + if (!(o instanceof ExamSection that)) return false; return new EqualsBuilder().append(id, that.id).isEquals(); } diff --git a/app/models/sections/ExamSectionQuestion.java b/app/models/sections/ExamSectionQuestion.java index 040c62000b..aa5a7692fb 100644 --- a/app/models/sections/ExamSectionQuestion.java +++ b/app/models/sections/ExamSectionQuestion.java @@ -17,7 +17,16 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Transient; import java.math.BigDecimal; +import java.math.MathContext; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Comparator; @@ -25,19 +34,11 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeMap; -import java.util.stream.Collectors; import javax.annotation.Nonnull; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.Transient; import models.api.Scorable; import models.api.Sortable; import models.base.OwnedModel; @@ -47,14 +48,15 @@ import models.questions.Question; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; -import play.Logger; import play.mvc.Result; @Entity public class ExamSectionQuestion extends OwnedModel implements Comparable, Sortable, Scorable { - private static final Logger.ALogger logger = Logger.of(ExamSectionQuestion.class); + private final Logger logger = LoggerFactory.getLogger(ExamSectionQuestion.class); @ManyToOne @JoinColumn(name = "exam_section_id") @@ -104,14 +106,6 @@ public class ExamSectionQuestion extends OwnedModel implements Comparable optionMap; @@ -284,7 +278,7 @@ ExamSectionQuestion copy(boolean preserveOriginalQuestion, boolean setParent) { blueprint = question; options.forEach(o -> esqCopy.getOptions().add(o.copy())); } else { - // This is a little bit tricky. Need to map the original question options with copied ones so they can be + // This is a little bit tricky. Need to map the original question options with copied ones, so they can be // associated with both question and exam section question options :) Map optionMap; @@ -328,10 +322,9 @@ public boolean equals(Object o) { if (this == o) { return true; } - if (!(o instanceof ExamSectionQuestion)) { + if (!(o instanceof ExamSectionQuestion other)) { return false; } - ExamSectionQuestion other = (ExamSectionQuestion) o; return new EqualsBuilder().append(examSection, other.examSection).append(question, other.question).build(); } @@ -355,24 +348,22 @@ public void setOrdinal(Integer ordinal) { sequenceNumber = ordinal; } - @Transient @Override public Optional getValidationResult(JsonNode node) { return question.getValidationResult(node); } - @Transient @Override public Double getAssessedScore() { switch (question.getType()) { - case EssayQuestion: + case EssayQuestion -> { if (evaluationType == Question.EvaluationType.Points) { return essayAnswer == null || essayAnswer.getEvaluatedScore() == null ? 0 : essayAnswer.getEvaluatedScore(); } - break; - case MultipleChoiceQuestion: + } + case MultipleChoiceQuestion -> { if (forcedScore != null) { return forcedScore; } @@ -383,8 +374,8 @@ public Double getAssessedScore() { if (o.isPresent()) { return o.get().getOption().isCorrectOption() ? maxScore : 0.0; } - break; - case WeightedMultipleChoiceQuestion: + } + case WeightedMultipleChoiceQuestion -> { if (forcedScore != null) { return forcedScore; } @@ -392,10 +383,11 @@ public Double getAssessedScore() { .stream() .filter(esq -> esq.isAnswered() && esq.getScore() != null) .map(ExamSectionQuestionOption::getScore) - .reduce(0.0, (sum, x) -> sum += x); + .reduce(0.0, Double::sum); // ATM minimum score is zero return Math.max(0.0, evaluation); - case ClozeTestQuestion: + } + case ClozeTestQuestion -> { if (forcedScore != null) { return forcedScore; } @@ -410,9 +402,10 @@ public Double getAssessedScore() { return 0.0; } DecimalFormat df = new DecimalFormat("#.##", new DecimalFormatSymbols(Locale.US)); - double value = correct * maxScore / (correct + incorrect); + double value = (correct * maxScore) / (correct + incorrect); return Double.valueOf(df.format(value)); - case ClaimChoiceQuestion: + } + case ClaimChoiceQuestion -> { if (forcedScore != null) { return forcedScore; } @@ -424,59 +417,59 @@ public Double getAssessedScore() { return answeredOption.get().getScore(); } return 0.0; + } } return 0.0; } - @Transient @Override public Double getMaxAssessedScore() { switch (question.getType()) { - case EssayQuestion: + case EssayQuestion -> { if (evaluationType == Question.EvaluationType.Points) { return maxScore == null ? 0 : maxScore; } - break; - case MultipleChoiceQuestion: - case ClozeTestQuestion: + } + case MultipleChoiceQuestion, ClozeTestQuestion -> { return maxScore == null ? 0 : maxScore; - case WeightedMultipleChoiceQuestion: + } + case WeightedMultipleChoiceQuestion -> { return options .stream() .map(ExamSectionQuestionOption::getScore) .filter(score -> score != null && score > 0) - .reduce(0.0, (sum, x) -> sum += x); - case ClaimChoiceQuestion: + .reduce(0.0, Double::sum); + } + case ClaimChoiceQuestion -> { return options .stream() .map(ExamSectionQuestionOption::getScore) - .filter(score -> score != null) + .filter(Objects::nonNull) .max(Comparator.comparing(Double::valueOf)) .orElse(0.0); + } } return 0.0; } - @Transient public Double getMinScore() { if (question.getType() == Question.Type.WeightedMultipleChoiceQuestion) { return options .stream() .map(ExamSectionQuestionOption::getScore) .filter(score -> score != null && score < 0) - .reduce(0.0, (sum, x) -> sum += x); + .reduce(0.0, Double::sum); } else if (question.getType() == Question.Type.ClaimChoiceQuestion) { return options .stream() .map(ExamSectionQuestionOption::getScore) - .filter(score -> score != null) + .filter(Objects::nonNull) .min(Comparator.comparing(Double::valueOf)) .orElse(0.0); } return 0.0; } - @Transient @Override public boolean isRejected() { return ( @@ -488,7 +481,6 @@ public boolean isRejected() { ); } - @Transient @Override public boolean isApproved() { return ( @@ -507,7 +499,6 @@ public boolean isApproved() { * * @param option New option to add. */ - @Transient public void addOption(ExamSectionQuestionOption option, boolean preserveScores) { if (question.getType() == Question.Type.ClaimChoiceQuestion) return; @@ -524,16 +515,16 @@ public void addOption(ExamSectionQuestionOption option, boolean preserveScores) List opts = options .stream() .filter(o -> o.getScore() != null && o.getScore() > 0) - .collect(Collectors.toList()); + .toList(); BigDecimal delta = calculateOptionScores(option.getScore(), opts); - option.setScore(new BigDecimal(option.getScore()).add(delta).doubleValue()); + option.setScore(BigDecimal.valueOf(option.getScore()).add(delta).doubleValue()); } else if (option.getScore() < 0) { List opts = options .stream() .filter(o -> o.getScore() != null && o.getScore() < 0) - .collect(Collectors.toList()); + .toList(); BigDecimal delta = calculateOptionScores(option.getScore(), opts); - option.setScore(new BigDecimal(option.getScore()).add(delta).doubleValue()); + option.setScore(BigDecimal.valueOf(option.getScore()).add(delta).doubleValue()); } options.add(option); } @@ -541,12 +532,11 @@ public void addOption(ExamSectionQuestionOption option, boolean preserveScores) private void initOptionScore(Double score, List options) { BigDecimal delta = calculateOptionScores(score * -1, options); if (!options.isEmpty()) { - ExamSectionQuestionOption first = options.get(0); - first.setScore(new BigDecimal(first.getScore()).add(delta).doubleValue()); + ExamSectionQuestionOption first = options.getFirst(); + first.setScore(BigDecimal.valueOf(first.getScore()).add(delta).doubleValue()); } } - @Transient public void removeOption(MultipleChoiceOption option, boolean preserveScores) { if (question.getType() == Question.Type.ClaimChoiceQuestion) return; @@ -569,13 +559,13 @@ public void removeOption(MultipleChoiceOption option, boolean preserveScores) { List opts = options .stream() .filter(o -> o.getScore() != null && o.getScore() > 0) - .collect(Collectors.toList()); + .toList(); initOptionScore(score, opts); } else if (score < 0) { List opts = options .stream() .filter(o -> o.getScore() != null && o.getScore() < 0) - .collect(Collectors.toList()); + .toList(); initOptionScore(score, opts); } } @@ -588,7 +578,8 @@ private BigDecimal calculateOptionScores(double optionScore, List> getStudentEnrolments(User user) { public CompletionStage getRoomInfoForEnrolment(String hash, User user) { return CompletableFuture.supplyAsync( () -> { - ExpressionList query = Ebean + ExpressionList query = DB .find(ExamEnrolment.class) .fetch("user", "id") .fetch("user.language") @@ -96,7 +94,7 @@ public CompletionStage getRoomInfoForEnrolment(String hash, User user) private List doGetStudentEnrolments(User user) { DateTime now = dateTimeHandler.adjustDST(new DateTime()); - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .fetch("examinationEventConfiguration") .fetch("examinationEventConfiguration.examinationEvent") @@ -127,11 +125,14 @@ private List doGetStudentEnrolments(User user) { .endJunction() .findList() .stream() - .filter(ee -> - ee.getExaminationEventConfiguration() == null || - ee.getExaminationEventConfiguration().getExaminationEvent().getStart().isAfter((DateTime.now())) - ) - .collect(Collectors.toList()); + .filter(ee -> { + if (ee.getExaminationEventConfiguration() == null) { + return true; + } + var start = ee.getExaminationEventConfiguration().getExaminationEvent().getStart(); + return start.plusMinutes(ee.getExam().getDuration()).isAfterNow(); + }) + .toList(); enrolments.forEach(ee -> { Exam exam = ee.getExam(); if (exam != null && exam.getExamSections().stream().noneMatch(ExamSection::isOptional)) { @@ -143,16 +144,16 @@ private List doGetStudentEnrolments(User user) { .stream() .filter(ee -> { Exam exam = ee.getExam(); - if (exam != null && exam.getExamActiveEndDate() != null) { + if (exam != null && exam.getPeriodEnd() != null) { return ( - exam.getExamActiveEndDate().isAfterNow() && + exam.getPeriodEnd().isAfterNow() && exam.hasState(Exam.State.PUBLISHED, Exam.State.STUDENT_STARTED) ); } CollaborativeExam ce = ee.getCollaborativeExam(); - return ce != null && ce.getExamActiveEndDate().isAfterNow(); + return ce != null && ce.getPeriodEnd().isAfterNow(); }) - .collect(Collectors.toList()); + .toList(); } private Map doGetReservationHeaders(Http.RequestHeader request, Long userId) { @@ -240,7 +241,7 @@ private boolean isMachineOk(ExamEnrolment enrolment, Http.RequestHeader request, message = enrolment.getId() + ":::" + lookedUp.getId(); } headers.put(header, Base64.encodeBase64String(message.getBytes())); - logger.debug("room and machine not ok. " + message); + logger.debug("room and machine not ok. {}", message); return false; } } @@ -318,24 +319,25 @@ private boolean isInsideBounds(ExamEnrolment ee, int minutesToFuture) { ExaminationEvent event = ee.getExaminationEventConfiguration() != null ? ee.getExaminationEventConfiguration().getExaminationEvent() : null; + int delay = ee.getDelay(); return ( - ( - reservation != null && - reservation.getStartAt().isBefore(latest) && - reservation.getEndAt().isAfter(earliest) - ) || - ( - event != null && - event.getStart().isBefore(latest) && - event.getStart().plusMinutes(ee.getExam().getDuration()).isAfter(earliest) - ) + (reservation != null && + reservation.getStartAt().plusSeconds(delay).isBefore(latest) && + reservation.getEndAt().isAfter(earliest)) || + (event != null && + event.getStart().plusSeconds(delay).isBefore(latest) && + event.getStart().plusMinutes(ee.getExam().getDuration()).isAfter(earliest)) ); } private DateTime getStartTime(ExamEnrolment enrolment) { return enrolment.getReservation() != null - ? enrolment.getReservation().getStartAt() - : enrolment.getExaminationEventConfiguration().getExaminationEvent().getStart(); + ? enrolment.getReservation().getStartAt().plusSeconds(enrolment.getDelay()) + : enrolment + .getExaminationEventConfiguration() + .getExaminationEvent() + .getStart() + .plusSeconds(enrolment.getDelay()); } private Optional getNextEnrolment(Long userId, int minutesToFuture) { diff --git a/app/repository/ExaminationRepository.java b/app/repository/ExaminationRepository.java index 1253588f67..eabe8fa848 100644 --- a/app/repository/ExaminationRepository.java +++ b/app/repository/ExaminationRepository.java @@ -1,8 +1,8 @@ package repository; import controllers.iop.collaboration.api.CollaborativeExamLoader; -import io.ebean.Ebean; -import io.ebean.EbeanServer; +import io.ebean.DB; +import io.ebean.Database; import io.ebean.ExpressionList; import io.ebean.Query; import io.ebean.Transaction; @@ -27,36 +27,34 @@ import models.questions.Question; import models.sections.ExamSection; import org.joda.time.DateTime; -import play.Logger; -import play.db.ebean.EbeanConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import util.datetime.DateTimeHandler; public class ExaminationRepository { - private final EbeanServer db; + private final Database db; private final CollaborativeExamLoader cel; private final DatabaseExecutionContext ec; private final DateTimeHandler dateTimeHandler; - private static final Logger.ALogger logger = Logger.of(ExaminationRepository.class); + private final Logger logger = LoggerFactory.getLogger(ExaminationRepository.class); @Inject public ExaminationRepository( - EbeanConfig ebeanConfig, CollaborativeExamLoader cel, DatabaseExecutionContext databaseExecutionContext, DateTimeHandler dateTimeHandler ) { - this.db = Ebean.getServer(ebeanConfig.defaultServer()); + this.db = DB.getDefault(); this.cel = cel; this.ec = databaseExecutionContext; this.dateTimeHandler = dateTimeHandler; } private Optional doCreateExam(Exam prototype, User user, ExamEnrolment enrolment) { - Transaction txn = db.beginTransaction(); Optional result; - try { + try (Transaction tx = db.beginTransaction()) { boolean isCollaborative = enrolment.getCollaborativeExam() != null; Reservation reservation = enrolment.getReservation(); // TODO: support for optional sections in BYOD exams @@ -73,10 +71,8 @@ private Optional doCreateExam(Exam prototype, User user, ExamEnrolment enr db.save(studentExam); enrolment.setExam(studentExam); db.save(enrolment); - txn.commit(); + tx.commit(); result = Optional.of(studentExam); - } finally { - txn.end(); } return result; } @@ -154,7 +150,7 @@ public CompletionStage> getCollaborativeExam(String Optional exam = db.find(Exam.class).where().eq("hash", hash).findOneOrEmpty(); if (exam.isPresent()) { if (!exam.get().getExamEnrolments().isEmpty()) { - CollaborativeExam ce2 = exam.get().getExamEnrolments().get(0).getCollaborativeExam(); + CollaborativeExam ce2 = exam.get().getExamEnrolments().getFirst().getCollaborativeExam(); return ce2 == null ? Optional.empty() : Optional.of(ce2); } } @@ -245,12 +241,12 @@ public CompletionStage> findEnrolment( .findList() .stream() .filter(e -> allowFuture || isInEffect(e)) - .collect(Collectors.toList()); + .toList(); if (enrolments.size() > 1) { logger.error("multiple enrolments found during examination"); } - return enrolments.isEmpty() ? Optional.empty() : Optional.of(enrolments.get(0)); + return enrolments.isEmpty() ? Optional.empty() : Optional.of(enrolments.getFirst()); }, ec ); diff --git a/app/repository/UserRepository.java b/app/repository/UserRepository.java index 8ae66e730a..ff44316214 100644 --- a/app/repository/UserRepository.java +++ b/app/repository/UserRepository.java @@ -1,22 +1,21 @@ package repository; -import io.ebean.Ebean; -import io.ebean.EbeanServer; +import io.ebean.DB; +import io.ebean.Database; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import javax.inject.Inject; import models.User; -import play.db.ebean.EbeanConfig; public class UserRepository { - private final EbeanServer db; + private final Database db; private final DatabaseExecutionContext ec; @Inject - public UserRepository(EbeanConfig ebeanConfig, DatabaseExecutionContext databaseExecutionContext) { - this.db = Ebean.getServer(ebeanConfig.defaultServer()); + public UserRepository(DatabaseExecutionContext databaseExecutionContext) { + this.db = DB.getDefault(); this.ec = databaseExecutionContext; } diff --git a/app/sanitizers/Attrs.java b/app/sanitizers/Attrs.java index 8e0c40902f..3a69b6279d 100644 --- a/app/sanitizers/Attrs.java +++ b/app/sanitizers/Attrs.java @@ -35,7 +35,7 @@ public enum Attrs { public static final TypedKey ORG_REF = TypedKey.create("orgId"); public static final TypedKey EXAM_ID = TypedKey.create("examId"); public static final TypedKey GRADE_ID = TypedKey.create("gradeId"); - public static final TypedKey> ACCESSABILITES = TypedKey.create("accessabilities"); + public static final TypedKey> ACCESSIBILITIES = TypedKey.create("accessabilities"); public static final TypedKey> SECTION_IDS = TypedKey.create("sections"); public static final TypedKey> ID_COLLECTION = TypedKey.create("idCollection"); public static final TypedKey> REF_COLLECTION = TypedKey.create("refCollection"); @@ -50,7 +50,6 @@ public enum Attrs { public static final TypedKey EXAM_STATE = TypedKey.create("examState"); public static final TypedKey TYPE = TypedKey.create("type"); public static final TypedKey SHARED = TypedKey.create("shared"); - public static final TypedKey EXPANDED = TypedKey.create("expanded"); public static final TypedKey TRIAL_COUNT = TypedKey.create("trialCount"); public static final TypedKey LANG_INSPECTION_REQUIRED = TypedKey.create("langInspectionRequired"); public static final TypedKey AUTO_EVALUATION_CONFIG = TypedKey.create("autoEvaluationConfig"); @@ -61,6 +60,7 @@ public enum Attrs { public static final TypedKey COURSE_CODE = TypedKey.create("code"); public static final TypedKey ANONYMOUS = TypedKey.create("anonymous"); public static final TypedKey SETTINGS_PASSWORD = TypedKey.create("settingsPassword"); + public static final TypedKey QUIT_PASSWORD = TypedKey.create("quitPassword"); public static final TypedKey QUESTION_TEXT = TypedKey.create("question"); public static final TypedKey ANSWER_INSTRUCTIONS = TypedKey.create("answerInstructions"); public static final TypedKey EVALUATION_CRITERIA = TypedKey.create("evaluationCriteria"); diff --git a/app/sanitizers/BaseSanitizer.java b/app/sanitizers/BaseSanitizer.java index 8a34db5628..dd3e1a9bd0 100644 --- a/app/sanitizers/BaseSanitizer.java +++ b/app/sanitizers/BaseSanitizer.java @@ -3,15 +3,16 @@ import com.fasterxml.jackson.databind.JsonNode; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Http; import play.mvc.Result; import play.mvc.Results; -public abstract class BaseSanitizer extends play.mvc.Action.Simple { +abstract class BaseSanitizer extends play.mvc.Action.Simple { - protected play.Logger.ALogger logger() { - return Logger.of(getClass()); + protected Logger logger() { + return LoggerFactory.getLogger(getClass()); } @Override @@ -20,7 +21,7 @@ public CompletionStage call(Http.Request request) { try { return delegate.call(sanitize(request, body)); } catch (SanitizingException e) { - logger().error("Sanitizing error: " + e.getMessage(), e); + logger().error(String.format("Sanitizing error: %s", e.getMessage()), e); return CompletableFuture.completedFuture(Results.badRequest()); } } diff --git a/app/sanitizers/CalendarReservationSanitizer.java b/app/sanitizers/CalendarReservationSanitizer.java index 943e8b6b61..72cc3b17e5 100644 --- a/app/sanitizers/CalendarReservationSanitizer.java +++ b/app/sanitizers/CalendarReservationSanitizer.java @@ -40,7 +40,7 @@ protected Http.Request sanitize(Http.Request req, JsonNode body) throws Sanitizi aids.add(it.next().asInt()); } } - request = request.addAttr(Attrs.ACCESSABILITES, aids); + request = request.addAttr(Attrs.ACCESSIBILITIES, aids); // Optional section IDs Collection optionalSectionIds = new HashSet<>(); diff --git a/app/sanitizers/CommaJoinedListSanitizer.java b/app/sanitizers/CommaJoinedListSanitizer.java index c77f2e3ecc..38b9cc3c78 100644 --- a/app/sanitizers/CommaJoinedListSanitizer.java +++ b/app/sanitizers/CommaJoinedListSanitizer.java @@ -18,7 +18,6 @@ import com.fasterxml.jackson.databind.JsonNode; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; import play.mvc.Http; public class CommaJoinedListSanitizer extends BaseSanitizer { @@ -27,7 +26,7 @@ protected Http.Request sanitize(Http.Request req, JsonNode body) throws Sanitizi String args = SanitizingHelper .parse("ids", body, String.class) .orElseThrow(() -> new SanitizingException("bad list")); - List ids = Arrays.stream(args.split(",")).map(Long::parseLong).collect(Collectors.toList()); + List ids = Arrays.stream(args.split(",")).map(Long::parseLong).toList(); if (ids.isEmpty()) { throw new SanitizingException("empty list"); } diff --git a/app/sanitizers/ExamRecordSanitizer.java b/app/sanitizers/ExamRecordSanitizer.java index a6655508d8..b32e273881 100644 --- a/app/sanitizers/ExamRecordSanitizer.java +++ b/app/sanitizers/ExamRecordSanitizer.java @@ -17,7 +17,6 @@ import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; import play.mvc.Http; @@ -27,10 +26,7 @@ public class ExamRecordSanitizer extends BaseSanitizer { protected Http.Request sanitize(Http.Request req, JsonNode body) throws SanitizingException { if (body.has("params") && body.get("params").has("childIds")) { JsonNode node = body.get("params").get("childIds"); - Collection ids = StreamSupport - .stream(node.spliterator(), false) - .map(JsonNode::asLong) - .collect(Collectors.toList()); + Collection ids = StreamSupport.stream(node.spliterator(), false).map(JsonNode::asLong).toList(); return req.addAttr(Attrs.ID_COLLECTION, ids); } throw new SanitizingException("no ids"); diff --git a/app/sanitizers/ExamUpdateSanitizer.java b/app/sanitizers/ExamUpdateSanitizer.java index b9ff585d47..b11e473521 100644 --- a/app/sanitizers/ExamUpdateSanitizer.java +++ b/app/sanitizers/ExamUpdateSanitizer.java @@ -32,8 +32,8 @@ public class ExamUpdateSanitizer extends BaseSanitizer { @Override protected Http.Request sanitize(Http.Request req, JsonNode body) throws SanitizingException { Http.Request request = req; - Optional start = SanitizingHelper.parse("examActiveStartDate", body, Long.class); - Optional end = SanitizingHelper.parse("examActiveEndDate", body, Long.class); + Optional start = SanitizingHelper.parse("periodStart", body, Long.class); + Optional end = SanitizingHelper.parse("periodEnd", body, Long.class); Optional duration = SanitizingHelper.parse("duration", body, Integer.class); Optional state = SanitizingHelper.parseEnum("state", body, Exam.State.class); Optional examName = SanitizingHelper.parse("name", body, String.class); @@ -76,7 +76,6 @@ protected Http.Request sanitize(Http.Request req, JsonNode body) throws Sanitizi request = SanitizingHelper.sanitizeOptionalHtml("enrollInstruction", body, Attrs.ENROLMENT_INFORMATION, request); request = SanitizingHelper.sanitizeOptional("trialCount", body, Integer.class, Attrs.TRIAL_COUNT, request); - request = SanitizingHelper.sanitizeOptional("expanded", body, Boolean.class, Attrs.EXPANDED, request); request = SanitizingHelper.sanitizeOptional( "subjectToLanguageInspection", diff --git a/app/sanitizers/ExaminationEventSanitizer.java b/app/sanitizers/ExaminationEventSanitizer.java index 68a247ff79..a35931b7d4 100644 --- a/app/sanitizers/ExaminationEventSanitizer.java +++ b/app/sanitizers/ExaminationEventSanitizer.java @@ -26,7 +26,8 @@ public class ExaminationEventSanitizer extends BaseSanitizer { protected Http.Request sanitize(Http.Request req, JsonNode body) throws SanitizingException { if (body.has("config")) { JsonNode configNode = body.get("config"); - String pwd = configNode.path("settingsPassword").asText(null); + String settingsPassword = configNode.path("settingsPassword").asText(null); + String quitPassword = configNode.path("quitPassword").asText(null); JsonNode eventNode = configNode.get("examinationEvent"); DateTime dateTime = DateTime.parse(eventNode.get("start").asText(), ISODateTimeFormat.dateTime()); String description = eventNode.get("description").asText(); @@ -35,7 +36,8 @@ protected Http.Request sanitize(Http.Request req, JsonNode body) throws Sanitizi .addAttr(Attrs.START_DATE, dateTime) .addAttr(Attrs.DESCRIPTION, description) .addAttr(Attrs.CAPACITY, capacity) - .addAttr(Attrs.SETTINGS_PASSWORD, pwd); + .addAttr(Attrs.SETTINGS_PASSWORD, settingsPassword) + .addAttr(Attrs.QUIT_PASSWORD, quitPassword); } else { throw new SanitizingException("missing required data"); } diff --git a/app/sanitizers/ExternalRefCollectionSanitizer.java b/app/sanitizers/ExternalRefCollectionSanitizer.java index 11025689d7..31ffa471cd 100644 --- a/app/sanitizers/ExternalRefCollectionSanitizer.java +++ b/app/sanitizers/ExternalRefCollectionSanitizer.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; import play.mvc.Http; @@ -12,10 +11,7 @@ public class ExternalRefCollectionSanitizer extends BaseSanitizer { protected Http.Request sanitize(Http.Request req, JsonNode body) throws SanitizingException { if (body.has("params") && body.get("params").has("childIds")) { JsonNode node = body.get("params").get("childIds"); - Collection refs = StreamSupport - .stream(node.spliterator(), false) - .map(JsonNode::asText) - .collect(Collectors.toList()); + Collection refs = StreamSupport.stream(node.spliterator(), false).map(JsonNode::asText).toList(); return req.addAttr(Attrs.REF_COLLECTION, refs); } throw new SanitizingException("no refs"); diff --git a/app/sanitizers/SanitizingException.java b/app/sanitizers/SanitizingException.java index 3455f9c0b8..de2dd2b49e 100644 --- a/app/sanitizers/SanitizingException.java +++ b/app/sanitizers/SanitizingException.java @@ -15,7 +15,7 @@ package sanitizers; -class SanitizingException extends Exception { +public class SanitizingException extends Exception { SanitizingException(String msg) { super(msg); diff --git a/app/security/AuthenticatedAction.java b/app/security/AuthenticatedAction.java index 504f562815..6b3998e436 100644 --- a/app/security/AuthenticatedAction.java +++ b/app/security/AuthenticatedAction.java @@ -23,8 +23,9 @@ import javax.inject.Inject; import models.Role; import models.User; -import play.Logger; -import play.libs.concurrent.HttpExecutionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.libs.concurrent.ClassLoaderExecutionContext; import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; @@ -34,13 +35,13 @@ public class AuthenticatedAction extends Action { - private final HttpExecutionContext ec; + private final ClassLoaderExecutionContext ec; private final UserRepository userRepository; - private static final Logger.ALogger logger = Logger.of(AuthenticatedAction.class); + private final Logger logger = LoggerFactory.getLogger(AuthenticatedAction.class); @Inject - public AuthenticatedAction(HttpExecutionContext ec, UserRepository userRepository) { + public AuthenticatedAction(ClassLoaderExecutionContext ec, UserRepository userRepository) { this.ec = ec; this.userRepository = userRepository; } diff --git a/app/security/Authenticator.scala b/app/security/Authenticator.scala deleted file mode 100644 index 6585201de7..0000000000 --- a/app/security/Authenticator.scala +++ /dev/null @@ -1,20 +0,0 @@ -package security - -import io.ebean.Ebean -import models.User -import play.api.mvc.{AnyContent, Request, Result, Results} - -trait Authenticator { - - def forbid(): Result = Results.Unauthorized("Unauthorized") - - def getAuthorizedUser(request: Request[AnyContent], roles: Seq[String]): Option[User] = { - val role = request.session.get("role") - val id = request.session.get("id") - (role, id) match { - case (Some(r), Some(id)) if roles.isEmpty || roles.contains(r) => - Some(Ebean.find(classOf[User], id)) - case _ => None - } - } -} diff --git a/app/security/CombinedRoleAndPermissionHandler.java b/app/security/CombinedRoleAndPermissionHandler.java index faf3d902ac..31af74347d 100644 --- a/app/security/CombinedRoleAndPermissionHandler.java +++ b/app/security/CombinedRoleAndPermissionHandler.java @@ -36,7 +36,7 @@ public CompletionStage isAllowed( String[] config = meta.get().split(","); String pattern = config[0].substring(config[0].indexOf('=') + 1); String[] roles = { config[1].substring(config[1].indexOf('=') + 1) }; - Boolean anyMatch = Boolean.valueOf(config[2].substring(config[2].indexOf('=') + 1)); + boolean anyMatch = Boolean.parseBoolean(config[2].substring(config[2].indexOf('=') + 1)); return deadboltHandler .getSubject(request) .thenApplyAsync(s -> { diff --git a/app/security/DeadboltCache.java b/app/security/DeadboltCache.java index 2b6edc9eb8..703af0c897 100644 --- a/app/security/DeadboltCache.java +++ b/app/security/DeadboltCache.java @@ -23,14 +23,14 @@ import javax.inject.Singleton; @Singleton -public class DeadboltCache implements HandlerCache { +class DeadboltCache implements HandlerCache { private final AuthorizationHandler defaultHandler; private final Map handlers = new HashMap<>(); @Inject - public DeadboltCache(final AuthorizationHandler handler) { + DeadboltCache(final AuthorizationHandler handler) { this.defaultHandler = handler; handlers.put(defaultHandler.handlerName(), defaultHandler); } diff --git a/app/security/scala/Auth.scala b/app/security/scala/Auth.scala new file mode 100644 index 0000000000..95e6eda8c6 --- /dev/null +++ b/app/security/scala/Auth.scala @@ -0,0 +1,45 @@ +package security.scala + +import io.ebean.DB +import models.{Role, User} +import play.api.libs.typedmap.TypedKey +import play.api.mvc.Results._ +import play.api.mvc._ +import util.scala.JavaApiHelper + +import javax.inject.Inject +import scala.concurrent.{ExecutionContext, Future} + +object Auth: + val ATTR_USER: TypedKey[User] = TypedKey[User]("authenticatedUser") + case class AuthenticatedAction @Inject() (override val parser: BodyParsers.Default)(implicit + ec: AuthExecutionContext + ) extends ActionBuilderImpl(parser): + override def invokeBlock[A]( + request: Request[A], + block: Request[A] => Future[Result] + ): Future[Result] = + val failure = + Future.successful(Unauthorized(s"Blocked unauthorized access to ${request.path}")) + val attrs = request.session.data + if attrs.contains("id") && attrs.contains("role") then + Future { + Option(DB.find(classOf[User], attrs("id").toLong)) + }(executionContext).flatMap { + case Some(user) => + user.setLoginRole(Role.Name.valueOf(request.session("role"))) + block(request.addAttr(ATTR_USER, user)) + case None => failure + }(executionContext) + else failure + + def authorized(roles: Seq[Role.Name])(implicit ec: ExecutionContext): ActionFilter[Request] = + new ActionFilter[Request] { + override def executionContext: ExecutionContext = ec + + override def filter[A](input: Request[A]): Future[Option[Result]] = Future.successful { + input.session.get("role").map(Role.Name.valueOf) match + case Some(role) if roles.contains(role) => None + case _ => Some(Unauthorized) + } + } diff --git a/app/security/scala/AuthExecutionContext.scala b/app/security/scala/AuthExecutionContext.scala new file mode 100644 index 0000000000..46deeda077 --- /dev/null +++ b/app/security/scala/AuthExecutionContext.scala @@ -0,0 +1,15 @@ +package security.scala + +import com.google.inject.ImplementedBy +import org.apache.pekko.actor.ActorSystem +import play.api.libs.concurrent.CustomExecutionContext + +import javax.inject.Inject +import scala.concurrent.ExecutionContext + +@ImplementedBy(classOf[AuthExecutionContextImpl]) +trait AuthExecutionContext extends ExecutionContext + +class AuthExecutionContextImpl @Inject() (system: ActorSystem) + extends CustomExecutionContext(system, "database.dispatcher") + with AuthExecutionContext diff --git a/app/system/ApiError.java b/app/system/ApiError.java deleted file mode 100644 index 5c669c35f8..0000000000 --- a/app/system/ApiError.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system; - -/** - * Model to easily return JSend like error messages as JSON - * @see JSend - */ -class ApiError { - - private static final String STATUS = "error"; - - private String message; - - ApiError(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public String getStatus() { - return STATUS; - } -} diff --git a/app/system/App.java b/app/system/App.java deleted file mode 100644 index f7b8b3069b..0000000000 --- a/app/system/App.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system; - -import com.google.inject.AbstractModule; -import javax.inject.Singleton; -import play.libs.akka.AkkaGuiceSupport; -import system.actors.*; - -@Singleton -public class App extends AbstractModule implements AkkaGuiceSupport { - - @Override - protected void configure() { - bind(SystemInitializer.class).asEagerSingleton(); - bindActor(ExamAutoSaverActor.class, "exam-auto-saver-actor"); - bindActor(ReservationPollerActor.class, "reservation-checker-actor"); - bindActor(AutoEvaluationNotifierActor.class, "auto-evaluation-notifier-actor"); - bindActor(AssessmentTransferActor.class, "assessment-transfer-actor"); - bindActor(ExamExpirationActor.class, "exam-expiration-actor"); - bindActor(ReservationReminderActor.class, "reservation-reminder-actor"); - bindActor(CollaborativeAssessmentSenderActor.class, "collaborative-assessment-sender-actor"); - bindActor(ExternalExamExpirationActor.class, "external-exam-expiration-actor"); - } -} diff --git a/app/system/App.scala b/app/system/App.scala new file mode 100644 index 0000000000..748d3c17e5 --- /dev/null +++ b/app/system/App.scala @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and limitations under the Licence. + */ + +package system + +import com.google.inject.AbstractModule +import play.libs.pekko.PekkoGuiceSupport +import system.actors._ + +import javax.inject.Singleton + +@Singleton +class App extends AbstractModule with PekkoGuiceSupport: + override def configure(): Unit = + bind(classOf[SystemInitializer]).asEagerSingleton() + bindActor(classOf[ExamAutoSaverActor], "exam-auto-saver-actor") + bindActor(classOf[ReservationPollerActor], "reservation-checker-actor") + bindActor(classOf[AutoEvaluationNotifierActor], "auto-evaluation-notifier-actor") + bindActor(classOf[AssessmentTransferActor], "assessment-transfer-actor") + bindActor(classOf[ExamExpirationActor], "exam-expiration-actor") + bindActor(classOf[ReservationReminderActor], "reservation-reminder-actor") + bindActor(classOf[CollaborativeAssessmentSenderActor], "collaborative-assessment-sender-actor") + bindActor(classOf[ExternalExamExpirationActor], "external-exam-expiration-actor") diff --git a/app/system/AppFilters.scala b/app/system/AppFilters.scala index 137e718a01..bff54f2246 100644 --- a/app/system/AppFilters.scala +++ b/app/system/AppFilters.scala @@ -15,22 +15,24 @@ package system -import javax.inject.Inject import play.api.http.HttpFilters +import play.api.mvc.EssentialFilter import play.filters.cors.CORSFilter import play.filters.csp.CSPFilter import play.filters.csrf.CSRFFilter import play.filters.gzip.GzipFilter import play.filters.headers.SecurityHeadersFilter -class AppFilters @Inject()(securityHeadersFilter: SecurityHeadersFilter, - csrfFilter: CSRFFilter, - gzipFilter: GzipFilter, - corsFilter: CORSFilter, - cspFilter: CSPFilter, - systemFilter: SystemFilter) - extends HttpFilters { +import javax.inject.Inject + +class AppFilters @Inject() ( + securityHeadersFilter: SecurityHeadersFilter, + csrfFilter: CSRFFilter, + gzipFilter: GzipFilter, + corsFilter: CORSFilter, + cspFilter: CSPFilter, + systemFilter: SystemFilter +) extends HttpFilters: - override def filters = + override def filters: Seq[EssentialFilter] = Seq(securityHeadersFilter, csrfFilter, gzipFilter, corsFilter, cspFilter, systemFilter) -} diff --git a/app/system/AuditLogger.java b/app/system/AuditLogger.java deleted file mode 100644 index c53318b83f..0000000000 --- a/app/system/AuditLogger.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system; - -import org.joda.time.DateTime; -import play.Logger; -import play.mvc.Http; - -class AuditLogger { - - private static final Logger.ALogger logger = Logger.of(AuditLogger.class); - - public static void log(Http.Request request) { - String method = request.method(); - Http.Session session = request.session(); - String userString = session == null || session.get("id").isEmpty() - ? "user " - : String.format("user #%d [%s]", Long.parseLong(session.get("id").get()), session.get("email").orElse("")); - String uri = request.uri(); - StringBuilder logEntry = new StringBuilder( - String.format("%s %s %s %s", DateTime.now(), userString, method, uri) - ); - // Do not log body of data import request to avoid logs getting unreadable. - if (!method.equals("GET") && !method.equals("DELETE") && !request.path().equals("/integration/iop/import")) { - String body = request.body() == null || request.body().asJson() == null - ? null - : request.body().asJson().toString(); - logEntry.append(String.format(" data: %s", body)); - } - logger.debug(logEntry.toString()); - } -} diff --git a/app/system/AuditedAction.scala b/app/system/AuditedAction.scala new file mode 100644 index 0000000000..ff21d08b31 --- /dev/null +++ b/app/system/AuditedAction.scala @@ -0,0 +1,45 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package system + +import play.api.Logging +import play.api.mvc._ + +import javax.inject.Inject +import scala.concurrent.{ExecutionContext, Future} + +class AuditedAction @Inject() (parser: BodyParsers.Default)(implicit ec: ExecutionContext) + extends ActionBuilderImpl(parser) + with Logging: + override def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] = + log(request) + block(request) + + private def log[A](request: Request[A]): Unit = + val (method, session, uri) = (request.method, request.session, request.uri) + val userString = + if session.isEmpty || session.get("id").isEmpty then "user " + else + val (id, email) = (session.get("id").get, session.get("email").getOrElse("")) + s"user #$id [$email]" + val logEntry = s"$userString $method $uri" + // Do not log body of data import request to avoid logs getting unreadable. + if method == "POST" || method == "PUT" && request.path != "/integration/iop/import" then + val json = if !request.hasBody then None else request.body.asInstanceOf[AnyContent].asJson + logger.debug(s"$logEntry data: ${json.getOrElse("")}") + else logger.debug(logEntry) diff --git a/app/system/SystemErrorHandler.java b/app/system/SystemErrorHandler.java deleted file mode 100644 index 32dc71f1da..0000000000 --- a/app/system/SystemErrorHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system; - -import exceptions.MalformedDataException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import javax.persistence.OptimisticLockException; -import play.Logger; -import play.http.HttpErrorHandler; -import play.libs.Json; -import play.mvc.Http; -import play.mvc.Result; -import play.mvc.Results; - -public class SystemErrorHandler implements HttpErrorHandler { - - private static final Logger.ALogger logger = Logger.of(SystemErrorHandler.class); - - @Override - public CompletionStage onClientError(Http.RequestHeader request, int statusCode, String message) { - logger.warn("onClientError: {} {}, status: {}, msg: {}", request.method(), request.uri(), statusCode, message); - Result result; - switch (statusCode) { - case Http.Status.BAD_REQUEST: - result = Results.badRequest(Json.toJson(new ApiError(message))); - break; - case Http.Status.NOT_FOUND: - result = Results.notFound(Json.toJson(new ApiError(message))); - break; - case Http.Status.UNAUTHORIZED: - case Http.Status.FORBIDDEN: - result = Results.unauthorized(Json.toJson(new ApiError(message))); - break; - case Http.Status.REQUEST_ENTITY_TOO_LARGE: - result = Results.status(statusCode, Json.toJson(new ApiError(message))); - break; - default: - result = Results.internalServerError(Json.toJson(new ApiError(message))); - } - return CompletableFuture.completedFuture(result); - } - - @Override - public CompletionStage onServerError(Http.RequestHeader request, Throwable exception) { - logger.error("onServerError: {} {}", request.method(), request.uri(), exception); - Throwable cause = exception.getCause(); - String errorMessage = cause == null ? exception.getMessage() : cause.getMessage(); - Result result = Results.internalServerError(Json.toJson(new ApiError(errorMessage))); - if (cause != null) { - if (cause instanceof MalformedDataException) { - result = Results.badRequest(Json.toJson(errorMessage)); - } - if (cause instanceof IllegalArgumentException) { - result = Results.badRequest(Json.toJson(new ApiError(errorMessage))); - } - if (cause instanceof OptimisticLockException) { - result = Results.badRequest("sitnet_error_data_has_changed"); - } - } - return CompletableFuture.completedFuture(result); - } -} diff --git a/app/system/SystemErrorHandler.scala b/app/system/SystemErrorHandler.scala new file mode 100644 index 0000000000..95ab88da14 --- /dev/null +++ b/app/system/SystemErrorHandler.scala @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and limitations under the Licence. + */ + +package system + +import exceptions.MalformedDataException +import jakarta.persistence.OptimisticLockException +import play.api.Logging +import play.api.http.HttpErrorHandler +import play.api.mvc.Results.Status +import play.api.mvc.{RequestHeader, Result, Results} + +import javax.inject.Singleton +import scala.concurrent.Future +import scala.util.Failure + +@Singleton +class SystemErrorHandler extends HttpErrorHandler with Logging: + override def onClientError(request: RequestHeader, status: Int, message: String): Future[Result] = + logger.warn(s"onClientError: ${request.method} ${request.uri}, status: $status, msg: $message") + Future.successful(Status(status)) + + override def onServerError(request: RequestHeader, exception: Throwable): Future[Result] = + logger.error(s"onServerError: ${request.method}, ${request.uri}", exception) + val cause = exception.getCause + val errorMessage = if cause == null then exception.getMessage else cause.getMessage + val result = Failure(cause) match + case Failure(e: MalformedDataException) => Results.BadRequest(errorMessage) + case Failure(e: IllegalArgumentException) => Results.BadRequest(errorMessage) + case Failure(e: OptimisticLockException) => Results.BadRequest("i18n_error_data_has_changed") + case _ => Results.InternalServerError(errorMessage) + Future.successful(result) diff --git a/app/system/SystemFilter.scala b/app/system/SystemFilter.scala index f026114f9d..5e20a1944e 100644 --- a/app/system/SystemFilter.scala +++ b/app/system/SystemFilter.scala @@ -1,11 +1,11 @@ package system -import akka.stream.Materializer -import javax.inject.Inject +import org.apache.pekko.stream.Materializer import org.joda.time.DateTime import org.joda.time.format.ISODateTimeFormat import play.api.mvc.{Filter, RequestHeader, Result} +import javax.inject.Inject import scala.concurrent.{ExecutionContext, Future} object ResultImplicits { @@ -15,9 +15,9 @@ object ResultImplicits { } } -class SystemFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContext) extends Filter { +class SystemFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter { - val Headers = Seq( + val Headers: Seq[(String, String)] = Seq( ("x-exam-start-exam", "ongoingExamHash"), ("x-exam-upcoming-exam", "upcomingExamHash"), ("x-exam-wrong-machine", "wrongMachineData"), @@ -37,9 +37,11 @@ class SystemFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContex } case s => Some(s) } - val result = src.withHeaders(("Cache-Control", "no-cache;no-store"), - ("Pragma", "no-cache"), - ("Expires", "0")) + val result = src.withHeaders( + ("Cache-Control", "no-cache;no-store"), + ("Pragma", "no-cache"), + ("Expires", "0") + ) session match { case None => result.withNewSession case Some(s) => @@ -51,8 +53,7 @@ class SystemFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContex case path if path == "/app/session" && request.method == "GET" => s.get("upcomingExamHash") match { case Some(_) => // Don't let session expire when awaiting exam to start - response.withSession( - s + ("since" -> ISODateTimeFormat.dateTime.print(DateTime.now))) + response.withSession(s + ("since" -> ISODateTimeFormat.dateTime.print(DateTime.now))) case _ => response.withSession(s) } case path if path.contains("logout") => response.withSession(s) diff --git a/app/system/SystemInitializer.java b/app/system/SystemInitializer.java index 96cffe189b..a769b4590d 100644 --- a/app/system/SystemInitializer.java +++ b/app/system/SystemInitializer.java @@ -15,27 +15,29 @@ package system; -import akka.actor.ActorRef; -import akka.actor.ActorSystem; -import akka.actor.Cancellable; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.TimeZone; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import models.User; +import org.apache.pekko.actor.ActorRef; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.actor.Cancellable; import org.joda.time.DateTime; import org.joda.time.DateTimeConstants; import org.joda.time.DateTimeZone; import org.joda.time.Seconds; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.Environment; import play.inject.ApplicationLifecycle; import repository.DatabaseExecutionContext; import scala.concurrent.duration.Duration; @@ -62,7 +64,7 @@ class SystemInitializer { private static final int EXTERNAL_EXAM_EXPIRATION_POLLER_START_AFTER_SECONDS = 100; private static final int EXTERNAL_EXAM_EXPIRATION_POLLER_INTERVAL_DAYS = 1; - private static final Logger.ALogger logger = Logger.of(SystemInitializer.class); + private final Logger logger = LoggerFactory.getLogger(SystemInitializer.class); private final EmailComposer composer; private final ActorSystem system; @@ -78,6 +80,7 @@ class SystemInitializer { EmailComposer composer, ConfigReader configReader, DatabaseExecutionContext ec, + Environment env, @Named("exam-auto-saver-actor") ActorRef examAutoSaver, @Named("reservation-checker-actor") ActorRef reservationChecker, @Named("auto-evaluation-notifier-actor") ActorRef autoEvaluationNotifier, @@ -92,7 +95,7 @@ class SystemInitializer { this.ec = ec; this.defaultTimeZone = configReader.getDefaultTimeZone(); - String encoding = System.getProperty("file.encoding"); + String encoding = Charset.defaultCharset().displayName(); if (!encoding.equals("UTF-8")) { logger.warn( "Default encoding is other than UTF-8 ({}). " + @@ -100,117 +103,116 @@ class SystemInitializer { encoding ); } - - System.setProperty("user.timezone", "UTC"); - TimeZone.setDefault(TimeZone.getTimeZone("UTC")); DateTimeZone.setDefault(DateTimeZone.forID("UTC")); - tasks.put( - "AUTO_SAVER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(EXAM_AUTO_SAVER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(EXAM_AUTO_SAVER_INTERVAL_MINUTES, TimeUnit.MINUTES), - examAutoSaver, - "tick", - ec, - null - ) - ); - tasks.put( - "RESERVATION_POLLER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(RESERVATION_POLLER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(RESERVATION_POLLER_INTERVAL_HOURS, TimeUnit.HOURS), - reservationChecker, - "tick", - ec, - null - ) - ); - tasks.put( - "EXAM_EXPIRATION_POLLER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(EXAM_EXPIRATION_POLLER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(EXAM_EXPIRATION_POLLER_INTERVAL_DAYS, TimeUnit.DAYS), - examExpirationChecker, - "tick", - ec, - null - ) - ); - tasks.put( - "AUTO_EVALUATION_NOTIFIER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(AUTO_EVALUATION_NOTIFIER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(AUTO_EVALUATION_NOTIFIER_INTERVAL_MINUTES, TimeUnit.MINUTES), - autoEvaluationNotifier, - "tick", - ec, - null - ) - ); - tasks.put( - "EXTERNAL_EXAM_SENDER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(ASSESSMENT_TRANSFER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(ASSESSMENT_TRANSFER_INTERVAL_HOURS, TimeUnit.HOURS), - assessmentTransferrer, - "tick", - ec, - null - ) - ); - tasks.put( - "COLLABORATIVE_EXAM_SENDER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(COLLABORATIVE_ASSESSMENT_SENDER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(COLLABORATIVE_ASSESSMENT_SENDER_INTERVAL_MINUTES, TimeUnit.MINUTES), - collaborativeAssessmentSender, - "tick", - ec, - null - ) - ); - tasks.put( - "RESERVATION_REMINDER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(RESERVATION_REMINDER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(RESERVATION_REMINDER_INTERVAL_MINUTES, TimeUnit.MINUTES), - reservationReminder, - "tick", - ec, - null - ) - ); - tasks.put( - "EXTERNAL_EXAM_EXPIRATION_POLLER", - system - .scheduler() - .scheduleAtFixedRate( - Duration.create(EXTERNAL_EXAM_EXPIRATION_POLLER_START_AFTER_SECONDS, TimeUnit.SECONDS), - Duration.create(EXTERNAL_EXAM_EXPIRATION_POLLER_INTERVAL_DAYS, TimeUnit.DAYS), - externalExamExpirationChecker, - "tick", - ec, - null - ) - ); + if (!env.isTest()) { + tasks.put( + "AUTO_SAVER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(EXAM_AUTO_SAVER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(EXAM_AUTO_SAVER_INTERVAL_MINUTES, TimeUnit.MINUTES), + examAutoSaver, + "tick", + ec, + null + ) + ); + tasks.put( + "RESERVATION_POLLER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(RESERVATION_POLLER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(RESERVATION_POLLER_INTERVAL_HOURS, TimeUnit.HOURS), + reservationChecker, + "tick", + ec, + null + ) + ); + tasks.put( + "EXAM_EXPIRATION_POLLER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(EXAM_EXPIRATION_POLLER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(EXAM_EXPIRATION_POLLER_INTERVAL_DAYS, TimeUnit.DAYS), + examExpirationChecker, + "tick", + ec, + null + ) + ); + tasks.put( + "AUTO_EVALUATION_NOTIFIER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(AUTO_EVALUATION_NOTIFIER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(AUTO_EVALUATION_NOTIFIER_INTERVAL_MINUTES, TimeUnit.MINUTES), + autoEvaluationNotifier, + "tick", + ec, + null + ) + ); + tasks.put( + "EXTERNAL_EXAM_SENDER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(ASSESSMENT_TRANSFER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(ASSESSMENT_TRANSFER_INTERVAL_HOURS, TimeUnit.HOURS), + assessmentTransferrer, + "tick", + ec, + null + ) + ); + tasks.put( + "COLLABORATIVE_EXAM_SENDER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(COLLABORATIVE_ASSESSMENT_SENDER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(COLLABORATIVE_ASSESSMENT_SENDER_INTERVAL_MINUTES, TimeUnit.MINUTES), + collaborativeAssessmentSender, + "tick", + ec, + null + ) + ); + tasks.put( + "RESERVATION_REMINDER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(RESERVATION_REMINDER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(RESERVATION_REMINDER_INTERVAL_MINUTES, TimeUnit.MINUTES), + reservationReminder, + "tick", + ec, + null + ) + ); + tasks.put( + "EXTERNAL_EXAM_EXPIRATION_POLLER", + system + .scheduler() + .scheduleAtFixedRate( + Duration.create(EXTERNAL_EXAM_EXPIRATION_POLLER_START_AFTER_SECONDS, TimeUnit.SECONDS), + Duration.create(EXTERNAL_EXAM_EXPIRATION_POLLER_INTERVAL_DAYS, TimeUnit.DAYS), + externalExamExpirationChecker, + "tick", + ec, + null + ) + ); - scheduleWeeklyReport(); + scheduleWeeklyReport(); + } lifecycle.addStopHook(() -> { logger.info("running shutdown hooks"); @@ -247,7 +249,7 @@ else if (adjustedHours != 5 && defaultTimeZone.isStandardOffset(nextRun.getMilli nextRun = nextRun.plusHours(1); } - logger.info("Scheduled next weekly report to be run at {}", nextRun.toString()); + logger.info("Scheduled next weekly report to be run at {}", nextRun); // Increase delay with one second so that this won't fire off before intended time. This may happen because of // millisecond-level rounding issues and possibly cause resending of messages. return Seconds.secondsBetween(now, nextRun).getSeconds() + 1; @@ -267,7 +269,7 @@ private void scheduleWeeklyReport() { delay, () -> { logger.info("Running weekly email report"); - List teachers = Ebean + List teachers = DB .find(User.class) .fetch("language") .where() diff --git a/app/system/SystemRequestHandler.java b/app/system/SystemRequestHandler.java index dd39921fab..6e2ac63f61 100644 --- a/app/system/SystemRequestHandler.java +++ b/app/system/SystemRequestHandler.java @@ -2,20 +2,42 @@ import java.lang.reflect.Method; import java.util.concurrent.CompletionStage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; public class SystemRequestHandler implements play.http.ActionCreator { + private static final Logger logger = LoggerFactory.getLogger(SystemRequestHandler.class); + @Override public Action createAction(Http.Request request, Method actionMethod) { return new Action.Simple() { @Override public CompletionStage call(Http.Request req) { - AuditLogger.log(req); + log(req); return delegate.call(req); } }; } + + private void log(Http.Request request) { + String method = request.method(); + Http.Session session = request.session(); + String userString = session == null || session.get("id").isEmpty() + ? "user " + : String.format("user #%d [%s]", Long.parseLong(session.get("id").get()), session.get("email").orElse("")); + String uri = request.uri(); + StringBuilder logEntry = new StringBuilder(String.format("%s %s %s", userString, method, uri)); + // Do not log body of data import request to avoid logs getting unreadable. + if (!method.equals("GET") && !method.equals("DELETE") && !request.path().equals("/integration/iop/import")) { + String body = request.body() == null || request.body().asJson() == null + ? null + : request.body().asJson().toString(); + logEntry.append(String.format(" data: %s", body)); + } + logger.debug(logEntry.toString()); + } } diff --git a/app/system/actors/AssessmentTransferActor.java b/app/system/actors/AssessmentTransferActor.java index bfac7d42fc..1e280e6e26 100644 --- a/app/system/actors/AssessmentTransferActor.java +++ b/app/system/actors/AssessmentTransferActor.java @@ -15,29 +15,32 @@ package system.actors; -import akka.actor.AbstractActor; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.PathProperties; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.util.List; import java.util.function.Function; import javax.inject.Inject; import models.ExamEnrolment; import models.json.ExternalExam; +import org.apache.pekko.actor.AbstractActor; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; +import play.mvc.Http; import util.config.ConfigReader; public class AssessmentTransferActor extends AbstractActor { - private static final Logger.ALogger logger = Logger.of(AssessmentTransferActor.class); + private final Logger logger = LoggerFactory.getLogger(AssessmentTransferActor.class); private final WSClient wsClient; private final ConfigReader configReader; @@ -55,7 +58,7 @@ public Receive createReceive() { String.class, s -> { logger.debug("Assessment transfer check started ->"); - List enrolments = Ebean + List enrolments = DB .find(ExamEnrolment.class) .where() .isNotNull("externalExam") @@ -79,27 +82,29 @@ public Receive createReceive() { private void send(ExamEnrolment enrolment) throws IOException { String ref = enrolment.getReservation().getExternalRef(); - logger.debug("Transferring back assessment for reservation " + ref); + logger.debug("Transferring back assessment for reservation {}", ref); URL url = parseUrl(ref); WSRequest request = wsClient.url(url.toString()); ExternalExam ee = enrolment.getExternalExam(); Function onSuccess = response -> { - if (response.getStatus() != 201) { - logger.error("Failed in transferring assessment for reservation " + ref); + if (response.getStatus() != Http.Status.CREATED) { + logger.error("Failed in transferring assessment for reservation {}", ref); } else { ee.setSent(DateTime.now()); ee.update(); - logger.info("Assessment transfer for reservation " + ref + " processed successfully"); + logger.info("Assessment transfer for reservation {} processed successfully", ref); } return null; }; - String json = Ebean.json().toJson(ee, PathProperties.parse("(*, creator(id))")); + String json = DB.json().toJson(ee, PathProperties.parse("(*, creator(id))")); ObjectMapper om = new ObjectMapper(); JsonNode node = om.readTree(json); request.post(node).thenApplyAsync(onSuccess); } private URL parseUrl(String reservationRef) throws MalformedURLException { - return new URL(configReader.getIopHost() + String.format("/api/enrolments/%s/assessment", reservationRef)); + return URI + .create(configReader.getIopHost() + String.format("/api/enrolments/%s/assessment", reservationRef)) + .toURL(); } } diff --git a/app/system/actors/AutoEvaluationNotifierActor.java b/app/system/actors/AutoEvaluationNotifierActor.java index 03932a3bda..a23d7b2f93 100644 --- a/app/system/actors/AutoEvaluationNotifierActor.java +++ b/app/system/actors/AutoEvaluationNotifierActor.java @@ -15,21 +15,22 @@ package system.actors; -import akka.actor.AbstractActor; import impl.EmailComposer; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.Optional; import javax.inject.Inject; import models.AutoEvaluationConfig; import models.Exam; import models.User; +import org.apache.pekko.actor.AbstractActor; import org.joda.time.DateTime; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import util.datetime.DateTimeHandler; public class AutoEvaluationNotifierActor extends AbstractActor { - private static final Logger.ALogger logger = Logger.of(AutoEvaluationNotifierActor.class); + private final Logger logger = LoggerFactory.getLogger(AutoEvaluationNotifierActor.class); private final EmailComposer composer; private final DateTimeHandler dateTimeHandler; @@ -47,7 +48,7 @@ public Receive createReceive() { String.class, s -> { logger.debug("Auto evaluation notification check started ->"); - Ebean + DB .find(Exam.class) .fetch("autoEvaluationConfig") .where() @@ -73,27 +74,18 @@ private DateTime adjustReleaseDate(DateTime date) { } private boolean isPastReleaseDate(Exam exam) { - Optional releaseDate; AutoEvaluationConfig config = exam.getAutoEvaluationConfig(); - switch (config.getReleaseType()) { - // Put some delay in these dates to avoid sending stuff in the middle of the night - case GIVEN_DATE: - releaseDate = Optional.of(adjustReleaseDate(new DateTime(config.getReleaseDate()))); - break; - case GIVEN_AMOUNT_DAYS: - releaseDate = - Optional.of(adjustReleaseDate(new DateTime(exam.getGradedTime()).plusDays(config.getAmountDays()))); - break; - case AFTER_EXAM_PERIOD: - releaseDate = Optional.of(adjustReleaseDate(new DateTime(exam.getExamActiveEndDate()).plusDays(1))); - break; - // Not handled at least by this actor - case IMMEDIATE: - case NEVER: - default: - releaseDate = Optional.empty(); - break; - } + Optional releaseDate = + switch (config.getReleaseType()) { + // Put some delay in these dates to avoid sending stuff in the middle of the night + case GIVEN_DATE -> Optional.of(adjustReleaseDate(new DateTime(config.getReleaseDate()))); + case GIVEN_AMOUNT_DAYS -> Optional.of( + adjustReleaseDate(new DateTime(exam.getGradedTime()).plusDays(config.getAmountDays())) + ); + case AFTER_EXAM_PERIOD -> Optional.of(adjustReleaseDate(new DateTime(exam.getPeriodEnd()).plusDays(1))); + // Not handled at least by this actor + default -> Optional.empty(); + }; return releaseDate.isPresent() && releaseDate.get().isBeforeNow(); } diff --git a/app/system/actors/CollaborativeAssessmentSenderActor.java b/app/system/actors/CollaborativeAssessmentSenderActor.java index b4e3f58690..c8f9a90d21 100644 --- a/app/system/actors/CollaborativeAssessmentSenderActor.java +++ b/app/system/actors/CollaborativeAssessmentSenderActor.java @@ -15,20 +15,21 @@ package system.actors; -import akka.actor.AbstractActor; import controllers.iop.collaboration.api.CollaborativeExamLoader; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.Query; import io.ebean.text.PathProperties; import java.util.List; import javax.inject.Inject; import models.Exam; import models.ExamParticipation; -import play.Logger; +import org.apache.pekko.actor.AbstractActor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CollaborativeAssessmentSenderActor extends AbstractActor { - private static final Logger.ALogger logger = Logger.of(CollaborativeAssessmentSenderActor.class); + private final Logger logger = LoggerFactory.getLogger(CollaborativeAssessmentSenderActor.class); private final CollaborativeExamLoader collaborativeExamLoader; @@ -44,7 +45,7 @@ public Receive createReceive() { String.class, s -> { logger.debug("Starting collaborative assessment sending check ->"); - Query query = Ebean.find(ExamParticipation.class); + Query query = DB.find(ExamParticipation.class); PathProperties pp = collaborativeExamLoader.getAssessmentPath(); pp.apply(query); List enrolments = query diff --git a/app/system/actors/ExamAutoSaverActor.java b/app/system/actors/ExamAutoSaverActor.java deleted file mode 100644 index 1344b532a6..0000000000 --- a/app/system/actors/ExamAutoSaverActor.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system.actors; - -import akka.actor.AbstractActor; -import controllers.SettingsController; -import impl.EmailComposer; -import io.ebean.Ebean; -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import javax.inject.Inject; -import models.Exam; -import models.ExamEnrolment; -import models.ExamInspection; -import models.ExamParticipation; -import models.ExaminationEvent; -import models.GeneralSettings; -import models.Reservation; -import models.User; -import models.json.ExternalExam; -import org.joda.time.DateTime; -import play.Logger; -import util.AppUtil; -import util.datetime.DateTimeHandler; - -public class ExamAutoSaverActor extends AbstractActor { - - private static final Logger.ALogger logger = Logger.of(ExamAutoSaverActor.class); - - private final EmailComposer composer; - private final DateTimeHandler dateTimeHandler; - - @Inject - public ExamAutoSaverActor(EmailComposer composer, DateTimeHandler dateTimeHandler) { - this.composer = composer; - this.dateTimeHandler = dateTimeHandler; - } - - @Override - public Receive createReceive() { - return receiveBuilder() - .match( - String.class, - s -> { - logger.debug("Starting check for ongoing exams ->"); - checkLocalExams(); - checkExternalExams(); - logger.debug("<- done"); - } - ) - .build(); - } - - private void checkLocalExams() { - List participations = Ebean - .find(ExamParticipation.class) - .fetch("exam") - .fetch("reservation") - .fetch("reservation.machine.room") - .fetch("examinationEvent") - .where() - .isNull("ended") - .or() - .isNotNull("reservation") - .isNotNull("examinationEvent") - .endOr() - .findList(); - - if (participations.isEmpty()) { - logger.debug("None found"); - return; - } - markEnded(participations); - } - - private DateTime getNow(ExamParticipation participation) { - if (participation.getExaminationEvent() != null) { - return DateTime.now(); - } - Reservation reservation = participation.getReservation(); - return dateTimeHandler.adjustDST(DateTime.now(), reservation.getMachine().getRoom()); - } - - private void markEnded(List participations) { - for (ExamParticipation participation : participations) { - Exam exam = participation.getExam(); - Reservation reservation = participation.getReservation(); - ExaminationEvent event = participation.getExaminationEvent(); - DateTime reservationStart = new DateTime(reservation == null ? event.getStart() : reservation.getStartAt()); - DateTime participationTimeLimit = reservationStart.plusMinutes(exam.getDuration()); - DateTime now = getNow(participation); - if (participationTimeLimit.isBefore(now)) { - participation.setEnded(now); - participation.setDuration( - new DateTime(participation.getEnded().getMillis() - participation.getStarted().getMillis()) - ); - - GeneralSettings settings = SettingsController.getOrCreateSettings("review_deadline", null, "14"); - int deadlineDays = Integer.parseInt(settings.getValue()); - DateTime deadline = new DateTime(participation.getEnded()).plusDays(deadlineDays); - participation.setDeadline(deadline); - - participation.save(); - logger.info("Setting exam {} state to REVIEW", exam.getId()); - exam.setState(Exam.State.REVIEW); - exam.save(); - if (exam.isPrivate()) { - // Notify teachers - Set recipients = new HashSet<>(); - recipients.addAll(exam.getParent().getExamOwners()); - recipients.addAll( - exam.getExamInspections().stream().map(ExamInspection::getUser).collect(Collectors.toSet()) - ); - AppUtil.notifyPrivateExamEnded(recipients, exam, composer); - } - } else { - logger.info("Exam {} is ongoing until {}", exam.getId(), participationTimeLimit); - } - } - } - - private void checkExternalExams() { - List enrolments = Ebean - .find(ExamEnrolment.class) - .fetch("externalExam") - .fetch("reservation") - .fetch("reservation.machine.room") - .where() - .isNotNull("externalExam") - .isNotNull("externalExam.started") - .isNull("externalExam.finished") - .isNotNull("reservation.externalRef") - .findList(); - for (ExamEnrolment enrolment : enrolments) { - ExternalExam exam = enrolment.getExternalExam(); - Exam content; - try { - content = exam.deserialize(); - } catch (IOException e) { - logger.error("Failed to parse content out of an external exam", e); - continue; - } - Reservation reservation = enrolment.getReservation(); - DateTime reservationStart = new DateTime(reservation.getStartAt()); - DateTime participationTimeLimit = reservationStart.plusMinutes(content.getDuration()); - DateTime now = dateTimeHandler.adjustDST(DateTime.now(), reservation.getMachine().getRoom()); - if (participationTimeLimit.isBefore(now)) { - exam.setFinished(now); - content.setState(Exam.State.REVIEW); - try { - exam.serialize(content); - logger.info("Setting external exam {} state to REVIEW", exam.getHash()); - } catch (IOException e) { - logger.error("failed to parse content out of an external exam", e); - } - } - } - } -} diff --git a/app/system/actors/ExamAutoSaverActor.scala b/app/system/actors/ExamAutoSaverActor.scala new file mode 100644 index 0000000000..b5345a7c84 --- /dev/null +++ b/app/system/actors/ExamAutoSaverActor.scala @@ -0,0 +1,135 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package system.actors + +import controllers.SettingsController +import impl.EmailComposer +import io.ebean.DB + +import java.io.IOException +import javax.inject.Inject +import models.{Exam, ExamEnrolment, ExamParticipation} +import org.apache.pekko.actor.AbstractActor +import org.joda.time.DateTime + +import play.api.Logging +import util.AppUtil +import util.datetime.DateTimeHandler +import util.scala.DbApiHelper + +import scala.jdk.CollectionConverters.* +import scala.util.control.Exception.catching + +class ExamAutoSaverActor @Inject (private val composer: EmailComposer, private val dateTimeHandler: DateTimeHandler) + extends AbstractActor + with Logging + with DbApiHelper: + + override def createReceive(): AbstractActor.Receive = receiveBuilder() + .`match`( + classOf[String], + (s: String) => + logger.debug("Starting check for ongoing exams ->") + checkLocalExams() + checkExternalExams() + logger.debug("<- done") + ) + .build + + private def checkLocalExams(): Unit = + val participants = DB + .find(classOf[ExamParticipation]) + .fetch("exam") + .fetch("reservation") + .fetch("reservation.machine.room") + .fetch("examinationEvent") + .where + .isNull("ended") + .or + .isNotNull("reservation") + .isNotNull("examinationEvent") + .endOr + .list + if participants.isEmpty then logger.debug("None found") + else markEnded(participants) + + private def getNow(participation: ExamParticipation) = + if Option(participation.getExaminationEvent).nonEmpty then DateTime.now + else + val reservation = participation.getReservation + dateTimeHandler.adjustDST(DateTime.now, reservation.getMachine.getRoom) + + private def markEnded(participants: List[ExamParticipation]): Unit = + participants.foreach(participation => + val exam = participation.getExam + val reservation = participation.getReservation + val event = participation.getExaminationEvent + val reservationStart = new DateTime( + if Option(reservation).isEmpty then event.getStart + else reservation.getStartAt + ) + val participationTimeLimit = reservationStart.plusMinutes(exam.getDuration) + val now = getNow(participation) + if participationTimeLimit.isBefore(now) then + participation.setEnded(now) + participation.setDuration(new DateTime(participation.getEnded.getMillis - participation.getStarted.getMillis)) + val settings = SettingsController.getOrCreateSettings("review_deadline", null, "14") + val deadlineDays = settings.getValue.toInt + val deadline = new DateTime(participation.getEnded).plusDays(deadlineDays) + participation.setDeadline(deadline) + participation.save() + logger.info(s"Setting exam ${exam.getId} state to REVIEW") + exam.save() + if exam.isPrivate then + // Notify teachers + val recipients = exam.getParent.getExamOwners.asScala ++ exam.getExamInspections.asScala.map(_.getUser) + AppUtil.notifyPrivateExamEnded(recipients.toSet, exam, composer) + else logger.info(s"Exam ${exam.getId} is ongoing until $participationTimeLimit") + ) + + private def checkExternalExams(): Unit = + DB + .find(classOf[ExamEnrolment]) + .fetch("externalExam") + .fetch("reservation") + .fetch("reservation.machine.room") + .where + .isNotNull("externalExam") + .isNotNull("externalExam.started") + .isNull("externalExam.finished") + .isNotNull("reservation.externalRef") + .list + .flatMap(enrolment => + catching(classOf[IOException]).either(enrolment.getExternalExam.deserialize()) match + case Left(e) => + logger.error("Failed to parse content out of an external exam", e) + None + case Right(content) => Some((enrolment, content)) + ) + .foreach((enrolment, content) => + val (exam, reservation) = (enrolment.getExternalExam, enrolment.getReservation) + val reservationStart = new DateTime(reservation.getStartAt) + val participationTimeLimit = reservationStart.plusMinutes(content.getDuration) + val now = dateTimeHandler.adjustDST(DateTime.now, reservation.getMachine.getRoom) + if participationTimeLimit.isBefore(now) then + exam.setFinished(now) + content.setState(Exam.State.REVIEW) + catching(classOf[IOException]).either(exam.serialize(content)) match + case Left(e) => logger.error("failed to parse content out of an external exam", e) + case Right(_) => logger.info(s"Setting external exam ${exam.getHash} state to REVIEW") + ) diff --git a/app/system/actors/ExamExpirationActor.java b/app/system/actors/ExamExpirationActor.java deleted file mode 100644 index 84f26a790f..0000000000 --- a/app/system/actors/ExamExpirationActor.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system.actors; - -import akka.actor.AbstractActor; -import io.ebean.Ebean; -import java.util.List; -import javax.inject.Inject; -import models.Exam; -import models.ExamRecord; -import org.joda.time.DateTime; -import play.Logger; -import util.config.ConfigReader; - -public class ExamExpirationActor extends AbstractActor { - - private static final Logger.ALogger logger = Logger.of(ExamExpirationActor.class); - - @Inject - private ConfigReader configReader; - - @Override - public Receive createReceive() { - return receiveBuilder() - .match( - String.class, - s -> { - logger.debug("Starting exam expiration check ->"); - List exams = Ebean - .find(Exam.class) - .where() - .disjunction() - .eq("state", Exam.State.GRADED_LOGGED) - .eq("state", Exam.State.ARCHIVED) - .eq("state", Exam.State.ABORTED) - .eq("state", Exam.State.REJECTED) - .endJunction() - .findList(); - - DateTime now = DateTime.now(); - for (Exam exam : exams) { - DateTime expirationDate = exam.getState() == Exam.State.ABORTED - ? exam.getExamParticipation().getEnded() - : exam.getGradedTime(); - if (expirationDate == null) { - logger.error("no grading time for exam {}", exam.getId()); - continue; - } - if (configReader.getExamExpirationDate(expirationDate).isBefore(now)) { - cleanExamData(exam); - logger.info("Marked exam {} as expired", exam.getId()); - } - } - logger.debug("<- done"); - } - ) - .build(); - } - - /** - * Disassociate exam from its creator, set state to deleted and erase any associated exam records - */ - private void cleanExamData(Exam exam) { - exam.setState(Exam.State.DELETED); - exam.setCreator(null); - exam.update(); - Ebean.find(ExamRecord.class).where().eq("exam", exam).findList().forEach(ExamRecord::delete); - } -} diff --git a/app/system/actors/ExamExpirationActor.scala b/app/system/actors/ExamExpirationActor.scala new file mode 100644 index 0000000000..aa2c216f2c --- /dev/null +++ b/app/system/actors/ExamExpirationActor.scala @@ -0,0 +1,78 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package system.actors + +import io.ebean.DB + +import javax.inject.Inject +import models.Exam +import models.ExamRecord +import org.apache.pekko.actor.AbstractActor +import org.joda.time.DateTime +import play.api.Logging +import util.config.ConfigReader +import util.scala.DbApiHelper + +import scala.jdk.CollectionConverters.* + +class ExamExpirationActor @Inject (private val configReader: ConfigReader) + extends AbstractActor + with DbApiHelper + with Logging: + + override def createReceive(): AbstractActor.Receive = receiveBuilder() + .`match`( + classOf[String], + (s: String) => + logger.debug("Starting exam expiration check ->") + val exams = DB + .find(classOf[Exam]) + .where + .disjunction + .eq("state", Exam.State.GRADED_LOGGED) + .eq("state", Exam.State.ARCHIVED) + .eq("state", Exam.State.ABORTED) + .eq("state", Exam.State.REJECTED) + .endJunction + .list + val now = DateTime.now + exams + .map(exam => + val expirationDate = + if exam.getState eq Exam.State.ABORTED then exam.getExamParticipation.getEnded + else exam.getGradedTime + (exam, Option(expirationDate)) + ) + .foreach((exam, expiration) => + expiration match + case Some(date) if configReader.getExamExpirationDate(date).isBeforeNow => + cleanExamData(exam) + logger.info(s"Marked exam ${exam.getId} as expired") + case None => logger.error(s"no grading time for exam ${exam.getId}") + case _ => // nothing to do + ) + logger.debug("<- done") + ) + .build + + // Disassociate exam from its creator, set state to deleted and erase any associated exam records + private def cleanExamData(exam: Exam): Unit = + exam.setState(Exam.State.DELETED) + exam.setCreator(null) + exam.update() + DB.find(classOf[ExamRecord]).where.eq("exam", exam).list.foreach(_.delete) diff --git a/app/system/actors/ExternalExamExpirationActor.java b/app/system/actors/ExternalExamExpirationActor.java deleted file mode 100644 index aa4a4a176e..0000000000 --- a/app/system/actors/ExternalExamExpirationActor.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system.actors; - -import akka.actor.AbstractActor; -import io.ebean.Ebean; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collections; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; -import javax.inject.Inject; -import models.Attachment; -import models.json.ExternalExam; -import models.questions.EssayAnswer; -import models.sections.ExamSectionQuestion; -import play.Logger; -import play.libs.ws.WSClient; -import util.config.ConfigReader; - -public class ExternalExamExpirationActor extends AbstractActor { - - private static final Logger.ALogger logger = Logger.of(ExternalExamExpirationActor.class); - private static final int MONTHS_UNTIL_EXPIRATION = 4; - - private final ConfigReader configReader; - private final WSClient wsClient; - - @Inject - public ExternalExamExpirationActor(ConfigReader configReader, WSClient wsClient) { - this.configReader = configReader; - this.wsClient = wsClient; - } - - private Optional parseUrl(String id) { - String url = configReader.getIopHost() + "/api/attachments/" + id; - try { - return Optional.of(new URL(url)); - } catch (MalformedURLException e) { - return Optional.empty(); - } - } - - private CompletableFuture deleteAttachment(Attachment attachment) { - Optional url = parseUrl(attachment.getExternalId()); - return CompletableFuture.runAsync(() -> url.ifPresent(value -> wsClient.url(value.toString()).delete())); - } - - @Override - public Receive createReceive() { - return receiveBuilder() - .match( - String.class, - s -> { - logger.debug("Starting external exam expiration check ->"); - Set exams = Ebean - .find(ExternalExam.class) - .where() - .isNotNull("sent") - .jsonExists("content", "id") - .findSet(); - - for (ExternalExam ee : exams) { - if (ee.getSent() == null) { - continue; - } - Set attachments = ee - .deserialize() - .getExamSections() - .stream() - .flatMap(es -> es.getSectionQuestions().stream()) - .map(ExamSectionQuestion::getEssayAnswer) - .filter(ea -> ea != null && ea.getAttachment() != null) - .map(EssayAnswer::getAttachment) - .collect(Collectors.toSet()); - CompletableFuture - .allOf(attachments.stream().map(this::deleteAttachment).toArray(CompletableFuture[]::new)) - .thenRunAsync(() -> { - if (ee.getSent().plusMonths(MONTHS_UNTIL_EXPIRATION).isBeforeNow()) { - ee.setContent(Collections.emptyMap()); - ee.update(); - logger.info("Marked external exam {} as expired", ee.getId()); - } - }); - } - logger.debug("<- done"); - } - ) - .build(); - } -} diff --git a/app/system/actors/ExternalExamExpirationActor.scala b/app/system/actors/ExternalExamExpirationActor.scala new file mode 100644 index 0000000000..0c41143929 --- /dev/null +++ b/app/system/actors/ExternalExamExpirationActor.scala @@ -0,0 +1,84 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package system.actors + +import io.ebean.DB + +import java.net.MalformedURLException +import java.net.URI +import java.net.URL +import java.util.concurrent.CompletableFuture +import javax.inject.Inject +import models.Attachment +import models.json.ExternalExam +import org.apache.pekko.actor.AbstractActor +import play.api.Logging +import play.libs.ws.WSClient +import util.config.ConfigReader +import util.scala.DbApiHelper + +import scala.jdk.CollectionConverters.* +import scala.util.control.Exception.catching + +object ExternalExamExpirationActor: + private val MONTHS_UNTIL_EXPIRATION = 4 +class ExternalExamExpirationActor @Inject (private val configReader: ConfigReader, private val wsClient: WSClient) + extends AbstractActor + with DbApiHelper + with Logging: + + private def parseUrl(id: String) = + val url = configReader.getIopHost + "/api/attachments/" + id + catching(classOf[MalformedURLException]).either(URI.create(url).toURL) match + case Left(_) => None + case Right(u) => Some(u) + + private def deleteAttachment(attachment: Attachment) = + val url = parseUrl(attachment.getExternalId) + CompletableFuture.runAsync(() => url.map((value: URL) => wsClient.url(value.toString).delete)) + + override def createReceive(): AbstractActor.Receive = receiveBuilder() + .`match`( + classOf[String], + (s: String) => + logger.debug("Starting external exam expiration check ->") + DB.find(classOf[ExternalExam]) + .where + .isNotNull("sent") + .jsonExists("content", "id") + .distinct + .filter(ee => Option(ee.getSent).nonEmpty) + .foreach(ee => + val attachments = ee.deserialize.getExamSections.asScala + .flatMap(_.getSectionQuestions.asScala) + .map(_.getEssayAnswer) + .filter(ea => Option(ea).nonEmpty && Option(ea.getAttachment).nonEmpty) + .map(_.getAttachment) + val promises = attachments.map(deleteAttachment).toArray + CompletableFuture + .allOf(promises: _*) + .thenRunAsync(() => + if ee.getSent.plusMonths(ExternalExamExpirationActor.MONTHS_UNTIL_EXPIRATION).isBeforeNow then + ee.setContent(Map.empty.asJava) + ee.update() + logger.info(s"Marked external exam ${ee.getId} as expired") + ) + ) + logger.debug("<- done") + ) + .build diff --git a/app/system/actors/ReservationPollerActor.java b/app/system/actors/ReservationPollerActor.java deleted file mode 100644 index 80b3dd76ec..0000000000 --- a/app/system/actors/ReservationPollerActor.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system.actors; - -import akka.actor.AbstractActor; -import impl.NoShowHandler; -import io.ebean.Ebean; -import java.util.List; -import java.util.stream.Collectors; -import javax.inject.Inject; -import models.ExamEnrolment; -import models.Reservation; -import org.joda.time.DateTime; -import play.Logger; -import util.datetime.DateTimeHandler; - -public class ReservationPollerActor extends AbstractActor { - - private static final Logger.ALogger logger = Logger.of(ReservationPollerActor.class); - - private final NoShowHandler noShowHandler; - private final DateTimeHandler dateTimeHandler; - - @Inject - public ReservationPollerActor(NoShowHandler noShowHandler, DateTimeHandler dateTimeHandler) { - this.noShowHandler = noShowHandler; - this.dateTimeHandler = dateTimeHandler; - } - - private boolean isPast(ExamEnrolment ee) { - DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - if (ee.getExaminationEventConfiguration() == null && ee.getReservation() != null) { - return ee.getReservation().getEndAt().isBefore(now); - } else if (ee.getExaminationEventConfiguration() != null) { - int duration = ee.getExam().getDuration(); - DateTime start = ee.getExaminationEventConfiguration().getExaminationEvent().getStart(); - return start.plusMinutes(duration).isBefore(now); - } - return false; - } - - @Override - public Receive createReceive() { - return receiveBuilder() - .match( - String.class, - s -> { - logger.debug("Starting no-show check ->"); - List enrolments = Ebean - .find(ExamEnrolment.class) - .fetch("exam") - .fetch("collaborativeExam") - .fetch("externalExam") - .fetch("reservation") - .fetch("examinationEventConfiguration.examinationEvent") - .where() - .eq("noShow", false) - .isNull("reservation.externalReservation") - .findList() - .stream() - .filter(this::isPast) - .collect(Collectors.toList()); - // The following are cases where external user has made a reservation but did not log in before - // reservation ended. Mark those as no-shows as well. - List reservations = Ebean - .find(Reservation.class) - .where() - .isNull("enrolment") - .isNotNull("externalRef") - .isNull("user") - .isNotNull("externalUserRef") - .eq("sentAsNoShow", false) - .lt("endAt", dateTimeHandler.adjustDST(DateTime.now())) - .findList(); - if (enrolments.isEmpty() && reservations.isEmpty()) { - logger.debug("None found"); - } else { - noShowHandler.handleNoShows(enrolments, reservations); - } - logger.debug("<- done"); - } - ) - .build(); - } -} diff --git a/app/system/actors/ReservationPollerActor.scala b/app/system/actors/ReservationPollerActor.scala new file mode 100644 index 0000000000..a0c870f553 --- /dev/null +++ b/app/system/actors/ReservationPollerActor.scala @@ -0,0 +1,86 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package system.actors + +import impl.NoShowHandler +import io.ebean.DB + +import javax.inject.Inject +import models.ExamEnrolment +import models.Reservation +import org.apache.pekko.actor.AbstractActor +import org.joda.time.DateTime +import play.api.Logging +import util.datetime.DateTimeHandler +import util.scala.DbApiHelper + +import scala.jdk.CollectionConverters.* + +class ReservationPollerActor @Inject ( + private val noShowHandler: NoShowHandler, + private val dateTimeHandler: DateTimeHandler +) extends AbstractActor + with Logging + with DbApiHelper: + + private def isPast(ee: ExamEnrolment): Boolean = + if ee.getExaminationEventConfiguration == null && ee.getReservation != null then + val now = dateTimeHandler.adjustDST(DateTime.now) + ee.getReservation.getEndAt.isBefore(now) + else if ee.getExaminationEventConfiguration != null then + val duration = ee.getExam.getDuration + val start = ee.getExaminationEventConfiguration.getExaminationEvent.getStart + start.plusMinutes(duration).isBeforeNow + else false + + override def createReceive(): AbstractActor.Receive = receiveBuilder() + .`match`( + classOf[String], + (s: String) => + logger.debug("Starting no-show check ->") + val enrolments = DB + .find(classOf[ExamEnrolment]) + .fetch("exam") + .fetch("collaborativeExam") + .fetch("externalExam") + .fetch("reservation") + .fetch("examinationEventConfiguration.examinationEvent") + .where + .eq("noShow", false) + .isNull("reservation.externalReservation") + .list + .filter(isPast) + + // The following are cases where external user has made a reservation but did not log in before + // reservation ended. Mark those as no-shows as well. + val reservations = DB + .find(classOf[Reservation]) + .where + .isNull("enrolment") + .isNotNull("externalRef") + .isNull("user") + .isNotNull("externalUserRef") + .eq("sentAsNoShow", false) + .lt("endAt", dateTimeHandler.adjustDST(DateTime.now)) + .list + + if enrolments.isEmpty && reservations.isEmpty then logger.debug("None found") + else noShowHandler.handleNoShows(enrolments.asJava, reservations.asJava) + logger.debug("<- done") + ) + .build diff --git a/app/system/actors/ReservationReminderActor.java b/app/system/actors/ReservationReminderActor.java deleted file mode 100644 index 00abfd6137..0000000000 --- a/app/system/actors/ReservationReminderActor.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package system.actors; - -import akka.actor.AbstractActor; -import impl.EmailComposer; -import io.ebean.Ebean; -import javax.inject.Inject; -import models.Reservation; -import org.joda.time.DateTime; -import play.Logger; -import util.datetime.DateTimeHandler; - -public class ReservationReminderActor extends AbstractActor { - - private static final Logger.ALogger logger = Logger.of(ReservationReminderActor.class); - - private final EmailComposer emailComposer; - private final DateTimeHandler dateTimeHandler; - - @Inject - public ReservationReminderActor(EmailComposer emailComposer, DateTimeHandler dateTimeHandler) { - this.emailComposer = emailComposer; - this.dateTimeHandler = dateTimeHandler; - } - - private void remind(Reservation r) { - emailComposer.composeReservationNotification(r.getUser(), r, r.getEnrolment().getExam(), true); - r.setReminderSent(true); - r.update(); - } - - @Override - public Receive createReceive() { - return receiveBuilder() - .match( - String.class, - s -> { - logger.debug("Starting reservation reminder task ->"); - DateTime now = dateTimeHandler.adjustDST(DateTime.now()); - DateTime tomorrow = now.plusDays(1); - Ebean - .find(Reservation.class) - .fetch("enrolment.optionalSections") - .fetch("enrolment.optionalSections.examMaterials") - .fetch("enrolment") - .fetch("enrolment.exam.examSections") - .fetch("enrolment.exam.examSections.examMaterials") - .where() - .isNotNull("enrolment.exam") - .between("startAt", now, tomorrow) - .ne("reminderSent", true) - .findList() - .forEach(this::remind); - logger.debug("<- done"); - } - ) - .build(); - } -} diff --git a/app/system/actors/ReservationReminderActor.scala b/app/system/actors/ReservationReminderActor.scala new file mode 100644 index 0000000000..f3015abd0d --- /dev/null +++ b/app/system/actors/ReservationReminderActor.scala @@ -0,0 +1,64 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package system.actors + +import impl.EmailComposer +import io.ebean.DB + +import javax.inject.Inject +import models.Reservation +import org.apache.pekko.actor.AbstractActor +import org.joda.time.DateTime +import play.api.Logging +import util.datetime.DateTimeHandler +import util.scala.DbApiHelper + +class ReservationReminderActor @Inject ( + private val emailComposer: EmailComposer, + private val dateTimeHandler: DateTimeHandler +) extends AbstractActor + with DbApiHelper + with Logging: + + private def remind(r: Reservation): Unit = + emailComposer.composeReservationNotification(r.getUser, r, r.getEnrolment.getExam, true) + r.setReminderSent(true) + r.update() + + override def createReceive(): AbstractActor.Receive = receiveBuilder() + .`match`( + classOf[String], + (s: String) => + logger.debug("Starting reservation reminder task ->") + val now = dateTimeHandler.adjustDST(DateTime.now) + val tomorrow = now.plusDays(1) + DB.find(classOf[Reservation]) + .fetch("enrolment.optionalSections") + .fetch("enrolment.optionalSections.examMaterials") + .fetch("enrolment") + .fetch("enrolment.exam.examSections") + .fetch("enrolment.exam.examSections.examMaterials") + .where + .isNotNull("enrolment.exam") + .between("startAt", now, tomorrow) + .ne("reminderSent", true) + .list + .foreach(remind) + logger.debug("<- done") + ) + .build diff --git a/app/system/interceptors/AnonymousJsonAction.java b/app/system/interceptors/AnonymousJsonAction.java index df1d616b9c..59bba0ecb7 100644 --- a/app/system/interceptors/AnonymousJsonAction.java +++ b/app/system/interceptors/AnonymousJsonAction.java @@ -16,13 +16,13 @@ package system.interceptors; -import akka.stream.Materializer; import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import javax.inject.Inject; +import org.apache.pekko.stream.Materializer; import play.libs.typedmap.TypedKey; import play.mvc.Http; import play.mvc.Result; diff --git a/app/system/interceptors/JsonFilterAction.java b/app/system/interceptors/JsonFilterAction.java index 9a33d07665..cfbd664568 100644 --- a/app/system/interceptors/JsonFilterAction.java +++ b/app/system/interceptors/JsonFilterAction.java @@ -16,22 +16,24 @@ package system.interceptors; -import akka.stream.Materializer; import com.fasterxml.jackson.databind.JsonNode; +import java.util.Arrays; import java.util.Collections; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import javax.validation.constraints.NotNull; +import org.apache.pekko.stream.Materializer; import play.http.HttpEntity; import play.libs.Json; import play.mvc.Action; import play.mvc.Result; +import scala.jdk.javaapi.CollectionConverters; import util.json.JsonFilter; abstract class JsonFilterAction extends Action { - private Materializer materializer; + private final Materializer materializer; JsonFilterAction(Materializer materializer) { this.materializer = materializer; @@ -45,7 +47,7 @@ CompletionStage filterJsonResponse(Result result, String... properties) @NotNull CompletionStage filterJsonResponse(Result result, Set ids, String... properties) { String contentType = result.contentType().orElse(""); - if (!contentType.toLowerCase().equals("application/json") || properties.length < 1) { + if (!contentType.equalsIgnoreCase("application/json") || properties.length < 1) { return CompletableFuture.completedFuture(result); } return result @@ -53,7 +55,11 @@ CompletionStage filterJsonResponse(Result result, Set ids, String. .consumeData(materializer) .thenApply(body -> { JsonNode json = Json.parse(body.decodeString("UTF-8")); - JsonFilter.filterProperties(json, true, ids, properties); + JsonFilter.filterProperties( + json, + CollectionConverters.asScala(ids).toSet(), + CollectionConverters.asScala(Arrays.asList(properties)).toSeq() + ); return new Result( result.status(), result.headers(), diff --git a/app/system/interceptors/SensitiveDataAction.java b/app/system/interceptors/SensitiveDataAction.java index e5b30762a4..20fbbfb7b4 100644 --- a/app/system/interceptors/SensitiveDataAction.java +++ b/app/system/interceptors/SensitiveDataAction.java @@ -15,9 +15,9 @@ package system.interceptors; -import akka.stream.Materializer; import com.google.inject.Inject; import java.util.concurrent.CompletionStage; +import org.apache.pekko.stream.Materializer; import play.mvc.Http; import play.mvc.Result; diff --git a/app/system/modules/ByodConfigModule.java b/app/system/modules/ByodConfigModule.java deleted file mode 100644 index 264fc67dc3..0000000000 --- a/app/system/modules/ByodConfigModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package system.modules; - -import com.google.inject.AbstractModule; -import util.config.ByodConfigHandler; -import util.config.ByodConfigHandlerImpl; - -public class ByodConfigModule extends AbstractModule { - - @Override - protected void configure() { - bind(ByodConfigHandler.class).to(ByodConfigHandlerImpl.class); - } -} diff --git a/app/system/modules/ByodConfigModule.scala b/app/system/modules/ByodConfigModule.scala new file mode 100644 index 0000000000..5f41fed15a --- /dev/null +++ b/app/system/modules/ByodConfigModule.scala @@ -0,0 +1,8 @@ +package system.modules + +import com.google.inject.AbstractModule +import util.config.ByodConfigHandler +import util.config.ByodConfigHandlerImpl + +class ByodConfigModule extends AbstractModule: + override def configure(): Unit = bind(classOf[ByodConfigHandler]).to(classOf[ByodConfigHandlerImpl]) diff --git a/app/system/modules/ConfigReaderModule.java b/app/system/modules/ConfigReaderModule.java deleted file mode 100644 index 4d34034c19..0000000000 --- a/app/system/modules/ConfigReaderModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package system.modules; - -import com.google.inject.AbstractModule; -import util.config.ConfigReader; -import util.config.ConfigReaderImpl; - -public class ConfigReaderModule extends AbstractModule { - - @Override - protected void configure() { - bind(ConfigReader.class).to(ConfigReaderImpl.class); - } -} diff --git a/app/system/modules/ConfigReaderModule.scala b/app/system/modules/ConfigReaderModule.scala new file mode 100644 index 0000000000..859fbf070a --- /dev/null +++ b/app/system/modules/ConfigReaderModule.scala @@ -0,0 +1,8 @@ +package system.modules + +import com.google.inject.AbstractModule +import util.config.ConfigReader +import util.config.ConfigReaderImpl + +class ConfigReaderModule extends AbstractModule: + override def configure(): Unit = bind(classOf[ConfigReader]).to(classOf[ConfigReaderImpl]) diff --git a/app/system/modules/DateTimeHandlerModule.java b/app/system/modules/DateTimeHandlerModule.java deleted file mode 100644 index 455d98e72b..0000000000 --- a/app/system/modules/DateTimeHandlerModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package system.modules; - -import com.google.inject.AbstractModule; -import util.datetime.DateTimeHandler; -import util.datetime.DateTimeHandlerImpl; - -public class DateTimeHandlerModule extends AbstractModule { - - @Override - protected void configure() { - bind(DateTimeHandler.class).to(DateTimeHandlerImpl.class); - } -} diff --git a/app/system/modules/DateTimeHandlerModule.scala b/app/system/modules/DateTimeHandlerModule.scala new file mode 100644 index 0000000000..463774f5cd --- /dev/null +++ b/app/system/modules/DateTimeHandlerModule.scala @@ -0,0 +1,8 @@ +package system.modules + +import com.google.inject.AbstractModule +import util.datetime.DateTimeHandler +import util.datetime.DateTimeHandlerImpl + +class DateTimeHandlerModule extends AbstractModule: + override def configure(): Unit = bind(classOf[DateTimeHandler]).to(classOf[DateTimeHandlerImpl]) diff --git a/app/system/modules/ExcelBuilderModule.java b/app/system/modules/ExcelBuilderModule.java deleted file mode 100644 index a8a99c805b..0000000000 --- a/app/system/modules/ExcelBuilderModule.java +++ /dev/null @@ -1,15 +0,0 @@ -package system.modules; - -import com.google.inject.AbstractModule; -import util.config.ByodConfigHandler; -import util.config.ByodConfigHandlerImpl; -import util.excel.ExcelBuilder; -import util.excel.ExcelBuilderImpl; - -public class ExcelBuilderModule extends AbstractModule { - - @Override - protected void configure() { - bind(ExcelBuilder.class).to(ExcelBuilderImpl.class); - } -} diff --git a/app/system/modules/ExcelBuilderModule.scala b/app/system/modules/ExcelBuilderModule.scala new file mode 100644 index 0000000000..8ba615e54e --- /dev/null +++ b/app/system/modules/ExcelBuilderModule.scala @@ -0,0 +1,8 @@ +package system.modules + +import com.google.inject.AbstractModule +import util.excel.ExcelBuilder +import util.excel.ExcelBuilderImpl + +class ExcelBuilderModule extends AbstractModule: + override def configure(): Unit = bind(classOf[ExcelBuilder]).to(classOf[ExcelBuilderImpl]) diff --git a/app/system/modules/FileHandlerModule.java b/app/system/modules/FileHandlerModule.java deleted file mode 100644 index 97c8bc8280..0000000000 --- a/app/system/modules/FileHandlerModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package system.modules; - -import com.google.inject.AbstractModule; -import util.file.FileHandler; -import util.file.FileHandlerImpl; - -public class FileHandlerModule extends AbstractModule { - - @Override - protected void configure() { - bind(FileHandler.class).to(FileHandlerImpl.class); - } -} diff --git a/app/system/modules/FileHandlerModule.scala b/app/system/modules/FileHandlerModule.scala new file mode 100644 index 0000000000..5c6d621a1a --- /dev/null +++ b/app/system/modules/FileHandlerModule.scala @@ -0,0 +1,8 @@ +package system.modules + +import com.google.inject.AbstractModule +import util.file.FileHandler +import util.file.FileHandlerImpl + +class FileHandlerModule extends AbstractModule: + override def configure(): Unit = bind(classOf[FileHandler]).to(classOf[FileHandlerImpl]) diff --git a/app/system/modules/MoodleXmlConverterModule.java b/app/system/modules/MoodleXmlConverterModule.java deleted file mode 100644 index edc48b258f..0000000000 --- a/app/system/modules/MoodleXmlConverterModule.java +++ /dev/null @@ -1,16 +0,0 @@ -package system.modules; - -import com.google.inject.AbstractModule; -import util.xml.MoodleXmlExporter; -import util.xml.MoodleXmlExporterImpl; -import util.xml.MoodleXmlImporter; -import util.xml.MoodleXmlImporterImpl; - -public class MoodleXmlConverterModule extends AbstractModule { - - @Override - protected void configure() { - bind(MoodleXmlExporter.class).to(MoodleXmlExporterImpl.class); - bind(MoodleXmlImporter.class).to(MoodleXmlImporterImpl.class); - } -} diff --git a/app/system/modules/MoodleXmlConverterModule.scala b/app/system/modules/MoodleXmlConverterModule.scala new file mode 100644 index 0000000000..22dc9c58c9 --- /dev/null +++ b/app/system/modules/MoodleXmlConverterModule.scala @@ -0,0 +1,12 @@ +package system.modules + +import com.google.inject.AbstractModule +import util.xml.MoodleXmlExporter +import util.xml.MoodleXmlExporterImpl +import util.xml.MoodleXmlImporter +import util.xml.MoodleXmlImporterImpl + +class MoodleXmlConverterModule extends AbstractModule: + override def configure(): Unit = + bind(classOf[MoodleXmlExporter]).to(classOf[MoodleXmlExporterImpl]) + bind(classOf[MoodleXmlImporter]).to(classOf[MoodleXmlImporterImpl]) diff --git a/app/util/AppUtil.java b/app/util/AppUtil.java deleted file mode 100644 index 301551a79d..0000000000 --- a/app/util/AppUtil.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package util; - -import impl.EmailComposer; -import java.util.Collection; -import models.Exam; -import models.User; -import play.Logger; - -public final class AppUtil { - - private static final Logger.ALogger logger = Logger.of(AppUtil.class); - - private AppUtil() {} - - public static void notifyPrivateExamEnded(Collection recipients, Exam exam, EmailComposer composer) { - for (User r : recipients) { - composer.composePrivateExamEnded(r, exam); - logger.info("Email sent to {}", r.getEmail()); - } - } -} diff --git a/app/models/dto/Credentials.java b/app/util/AppUtil.scala similarity index 65% rename from app/models/dto/Credentials.java rename to app/util/AppUtil.scala index 04f9efbf43..265b774168 100644 --- a/app/models/dto/Credentials.java +++ b/app/util/AppUtil.scala @@ -13,26 +13,17 @@ * See the Licence for the specific language governing permissions and limitations under the Licence. */ -package models.dto; +package util -public class Credentials { +import impl.EmailComposer +import models.Exam +import models.User +import play.api.Logger - private String username; - private String password; - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} +object AppUtil: + private val logger = Logger(this.getClass) + def notifyPrivateExamEnded(recipients: Set[User], exam: Exam, composer: EmailComposer): Unit = + recipients.foreach(r => + composer.composePrivateExamEnded(r, exam) + logger.info(s"Email sent to ${r.getEmail}") + ) diff --git a/app/util/config/ByodConfigHandler.scala b/app/util/config/ByodConfigHandler.scala index 57e7758d69..c6513f308c 100644 --- a/app/util/config/ByodConfigHandler.scala +++ b/app/util/config/ByodConfigHandler.scala @@ -1,13 +1,12 @@ package util.config -import java.util.Optional - import play.mvc.{Http, Result} -trait ByodConfigHandler { - def getExamConfig(hash: String, pwd: Array[Byte], salt: String): Array[Byte] - def calculateConfigKey(hash: String): String +import java.util.Optional + +trait ByodConfigHandler: + def getExamConfig(hash: String, pwd: Array[Byte], salt: String, quitPwd: String): Array[Byte] + def calculateConfigKey(hash: String, quitPwd: String): String def getPlaintextPassword(pwd: Array[Byte], salt: String): String def getEncryptedPassword(pwd: String, salt: String): Array[Byte] def checkUserAgent(request: Http.RequestHeader, examConfigKey: String): Optional[Result] -} diff --git a/app/util/config/ByodConfigHandlerImpl.scala b/app/util/config/ByodConfigHandlerImpl.scala index bec1ad09f1..b4ad30b6f9 100644 --- a/app/util/config/ByodConfigHandlerImpl.scala +++ b/app/util/config/ByodConfigHandlerImpl.scala @@ -1,24 +1,24 @@ package util.config -import java.io.ByteArrayOutputStream -import java.net.URL -import java.nio.charset.StandardCharsets -import java.util.Optional -import java.util.zip.GZIPOutputStream - -import javax.inject.Inject import org.apache.commons.codec.digest.DigestUtils import org.cryptonode.jncryptor.AES256JNCryptor import play.Environment -import play.api.Logger +import play.api.Logging import play.api.libs.json._ import play.mvc.{Http, Result, Results} -import scala.compat.java8.OptionConverters._ +import java.io.ByteArrayOutputStream +import java.net.URI +import java.nio.charset.StandardCharsets +import java.util.Optional +import java.util.zip.GZIPOutputStream +import javax.inject.Inject +import javax.xml.parsers.SAXParserFactory import scala.io.Source +import scala.jdk.OptionConverters._ import scala.xml.{Node, XML} -object ByodConfigHandlerImpl { +object ByodConfigHandlerImpl: private val StartUrlPlaceholder = "*** startURL ***" private val QuitPwdPlaceholder = "*** quitPwd ***" private val QuitLinkPlaceholder = "*** quitLink ***" @@ -27,26 +27,25 @@ object ByodConfigHandlerImpl { private val PasswordEncryption = "pswd" private val ConfigKeyHeader = "X-SafeExamBrowser-ConfigKeyHash" private val IgnoredKeys = Seq("originatorVersion") -} -class ByodConfigHandlerImpl @Inject()(configReader: ConfigReader, env: Environment) - extends ByodConfigHandler { + +class ByodConfigHandlerImpl @Inject() (configReader: ConfigReader, env: Environment) + extends ByodConfigHandler + with Logging: import ByodConfigHandlerImpl._ - private val logger = Logger(this.getClass).logger private val crypto = new AES256JNCryptor private val encryptionKey = configReader.getSettingsPasswordEncryptionKey /* FIXME: have Apache provide us with X-Forwarded-Proto header so we can resolve this automatically */ - private val protocol = new URL(configReader.getHostName).getProtocol + private val protocol = URI.create(configReader.getHostName).toURL.getProtocol - private def getTemplate(hash: String): String = { + private def getTemplate(hash: String, quitPwdPlain: String) = val path = s"${env.rootPath.getAbsolutePath}/conf/seb.template.plist" val startUrl = s"${configReader.getHostName}?exam=$hash" val quitLink = configReader.getQuitExaminationLink val adminPwd = DigestUtils.sha256Hex(configReader.getExaminationAdminPassword) - val quitPwdPlain = configReader.getQuitPassword val quitPwd = DigestUtils.sha256Hex(quitPwdPlain) - val allowQuitting = if (quitPwdPlain.isEmpty) "" else "" + val allowQuitting = if quitPwdPlain.isEmpty then "" else "" val source = Source.fromFile(path) val template = source.mkString .replace(StartUrlPlaceholder, startUrl) @@ -56,39 +55,35 @@ class ByodConfigHandlerImpl @Inject()(configReader: ConfigReader, env: Environme .replace(AllowQuittingPlaceholder, allowQuitting) source.close template - } - private def compress(data: Array[Byte]): Array[Byte] = { + private def compress(data: Array[Byte]) = val os = new ByteArrayOutputStream val gzip = new GZIPOutputStream(os) gzip.write(data) gzip.flush() gzip.close() os.toByteArray - } - private def compressWithHeader(data: Array[Byte]): Array[Byte] = { + private def compressWithHeader(data: Array[Byte]) = val header = PasswordEncryption.getBytes(StandardCharsets.UTF_8) val os = new ByteArrayOutputStream() os.write(header) os.write(data) os.close() compress(os.toByteArray) - } - private def nodeToJson(node: Node): Option[JsValue] = node.label match { + private def nodeToJson(node: Node): Option[JsValue] = node.label match case "string" | "data" => - val text = if (node.child.nonEmpty) node.child.head.text else "" + val text = if node.child.nonEmpty then node.child.head.text else "" Some(JsString(text.trim.filterNot(_ == '\n'))) - case "true" => Some(JsBoolean(true)) - case "false" => Some(JsBoolean(false)) - case "integer" => Some(JsNumber(node.child.head.text.toInt)) - case "array" => Some(JsArray(node.child.flatMap(nodeToJson))) - case "dict" => dictToJson(node) - case _ => throw new NoSuchElementException - } - - private def dictToJson(dict: Node): Option[JsValue] = dict.child match { + case "true" => Some(JsBoolean(true)) + case "false" => Some(JsBoolean(false)) + case "integer" | "real" => Some(JsNumber(node.child.head.text.toInt)) + case "array" => Some(JsArray(node.child.flatMap(nodeToJson))) + case "dict" => dictToJson(node) + case _ => throw new NoSuchElementException + + private def dictToJson(dict: Node) = dict.child match case Seq() => None case children => val json: Seq[(String, JsValue)] = children @@ -101,50 +96,47 @@ class ByodConfigHandlerImpl @Inject()(configReader: ConfigReader, env: Environme .toSeq .sortBy(_._1.toLowerCase) Some(JsObject(json)) - } - override def getExamConfig(hash: String, pwd: Array[Byte], salt: String): Array[Byte] = { - val template = getTemplate(hash) + override def getExamConfig(hash: String, pwd: Array[Byte], salt: String, quitPwd: String): Array[Byte] = + val template = getTemplate(hash, quitPwd) val templateGz = compress(template.getBytes(StandardCharsets.UTF_8)) // Decrypt user defined setting password val plaintextPwd = getPlaintextPassword(pwd, salt) // Encrypt the config file using unencrypted password val cipherText = crypto.encryptData(templateGz, plaintextPwd.toCharArray) compressWithHeader(cipherText) - } - override def getPlaintextPassword(pwd: Array[Byte], salt: String): String = { + override def getPlaintextPassword(pwd: Array[Byte], salt: String): String = val saltedPwd = crypto.decryptData(pwd, encryptionKey.toCharArray) new String(saltedPwd, StandardCharsets.UTF_8).replace(salt, "") - } override def getEncryptedPassword(pwd: String, salt: String): Array[Byte] = crypto.encryptData((pwd + salt).getBytes(StandardCharsets.UTF_8), encryptionKey.toCharArray) override def checkUserAgent(request: Http.RequestHeader, configKey: String): Optional[Result] = - request.header(ConfigKeyHeader).asScala match { - case None => Some(Results.unauthorized("SEB headers missing")).asJava + request.header(ConfigKeyHeader).toScala match { + case None => Some(Results.unauthorized("SEB headers missing")).toJava case Some(digest) => val absoluteUrl = s"$protocol://${request.host}${request.uri}" - DigestUtils.sha256Hex(absoluteUrl + configKey) match { - case sha if sha == digest => None.asJava + DigestUtils.sha256Hex(absoluteUrl + configKey) match + case sha if sha == digest => None.toJava case sha => logger.warn( - "Config key mismatch for URL {} and exam config key {}. Digest received: {}", - absoluteUrl, - configKey, - sha) - Some(Results.unauthorized("Wrong configuration key digest")).asJava - } + s"Config key mismatch for URL $absoluteUrl and exam config key $configKey. Digest received: $sha" + ) + Some(Results.unauthorized("Wrong configuration key digest")).toJava } - override def calculateConfigKey(hash: String): String = { - val plist: Node = XML.loadString(getTemplate(hash)) + override def calculateConfigKey(hash: String, quitPwd: String): String = + // Override the DTD setting. We need it with PLIST format and in order to integrate with SBT + val parser = XML.withSAXParser { + val factory = SAXParserFactory.newInstance() + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false) + factory.newSAXParser() + } + val plist: Node = parser.loadString(getTemplate(hash, quitPwd)) // Construct a Json-like structure out of .plist and create a digest over it // See SEB documentation for details - dictToJson((plist \ "dict").head) match { + dictToJson((plist \ "dict").head) match case Some(json) => DigestUtils.sha256Hex(json.toString.replaceAll("\\\\\\\\", "\\\\")) case None => throw new NoSuchElementException - } - } -} diff --git a/app/util/config/ConfigReader.java b/app/util/config/ConfigReader.java index ae2c6e7635..b035e55268 100644 --- a/app/util/config/ConfigReader.java +++ b/app/util/config/ConfigReader.java @@ -10,7 +10,6 @@ public interface ConfigReader { DateTimeZone getDefaultTimeZone(); String getHostName(); Integer getMaxFileSize(); - String getExamMaxDate(); List getExamDurations(); Integer getExamMaxDuration(); Integer getExamMinDuration(); @@ -33,9 +32,9 @@ public interface ConfigReader { String getQuitExaminationLink(); String getExaminationAdminPassword(); String getSettingsPasswordEncryptionKey(); - String getQuitPassword(); String getHomeOrganisationRef(); Integer getMaxByodExaminationParticipantCount(); + boolean isByodExamCreationPermissionGrantedForNewUsers(); String getCourseCodePrefix(); String getIopHost(); boolean isApiKeyUsed(); @@ -50,6 +49,7 @@ public interface ConfigReader { String getCsrfCookie(); boolean isMultiStudentIdEnabled(); String getMultiStudentOrganisations(); + List getSupportedLanguages(); boolean hasPath(String path); String getString(String path); diff --git a/app/util/config/ConfigReaderImpl.java b/app/util/config/ConfigReaderImpl.java index 12f2d154a8..90593ae97b 100644 --- a/app/util/config/ConfigReaderImpl.java +++ b/app/util/config/ConfigReaderImpl.java @@ -16,7 +16,7 @@ package util.config; import com.typesafe.config.Config; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -32,7 +32,7 @@ public class ConfigReaderImpl implements ConfigReader { - private Config config; + private final Config config; @Inject public ConfigReaderImpl(Config config) { @@ -41,137 +41,126 @@ public ConfigReaderImpl(Config config) { @Override public DateTimeZone getDefaultTimeZone() { - String id = config.getString("sitnet.application.timezone"); + String id = config.getString("exam.application.timezone"); return DateTimeZone.forID(id); } @Override public String getHostName() { - return config.getString("sitnet.application.hostname"); + return config.getString("exam.application.hostname"); } @Override public Integer getMaxFileSize() { - return config.getInt("sitnet.attachment.maxsize"); - } - - @Override - public String getExamMaxDate() { - DateTime newDate = new DateTime(0); - Period period = Period.parse(config.getString("sitnet.exam.maxDate")); - return newDate.plus(period).toString(); + return config.getInt("exam.attachment.maxsize"); } @Override public List getExamDurations() { - String[] durations = config.getString("sitnet.exam.durations").split(","); - return Arrays.stream(durations).map(Integer::parseInt).collect(Collectors.toList()); + String[] durations = config.getString("exam.exam.durations").split(","); + return Arrays.stream(durations).map(Integer::parseInt).toList(); } @Override public Integer getExamMaxDuration() { - return config.getInt("sitnet.exam.maxDuration"); + return config.getInt("exam.exam.maxDuration"); } @Override public Integer getExamMinDuration() { - return config.getInt("sitnet.exam.minDuration"); + return config.getInt("exam.exam.minDuration"); } @Override public Map> getRoleMapping() { - Role student = Ebean.find(Role.class).where().eq("name", Role.Name.STUDENT.toString()).findOne(); - Role teacher = Ebean.find(Role.class).where().eq("name", Role.Name.TEACHER.toString()).findOne(); - Role admin = Ebean.find(Role.class).where().eq("name", Role.Name.ADMIN.toString()).findOne(); + Role student = DB.find(Role.class).where().eq("name", Role.Name.STUDENT.toString()).findOne(); + Role teacher = DB.find(Role.class).where().eq("name", Role.Name.TEACHER.toString()).findOne(); + Role admin = DB.find(Role.class).where().eq("name", Role.Name.ADMIN.toString()).findOne(); Map> roles = new HashMap<>(); - roles.put(student, config.getStringList("sitnet.roles.student")); - roles.put(teacher, config.getStringList("sitnet.roles.teacher")); - roles.put(admin, config.getStringList("sitnet.roles.admin")); + roles.put(student, config.getStringList("exam.roles.student")); + roles.put(teacher, config.getStringList("exam.roles.teacher")); + roles.put(admin, config.getStringList("exam.roles.admin")); return roles; } @Override public boolean isCourseGradeScaleOverridable() { - return config.getBoolean("sitnet.course.gradescale.overridable"); + return config.getBoolean("exam.course.gradescale.overridable"); } @Override public boolean isEnrolmentPermissionCheckActive() { - return config.getBoolean("sitnet.integration.enrolmentPermissionCheck.active"); + return config.getBoolean("exam.integration.enrolmentPermissionCheck.active"); } @Override public boolean isVisitingExaminationSupported() { - return config.getBoolean("sitnet.integration.iop.visit.active"); + return config.getBoolean("exam.integration.iop.visit.active"); } @Override public boolean isCollaborationExaminationSupported() { - return config.getBoolean("sitnet.integration.iop.collaboration.active"); + return config.getBoolean("exam.integration.iop.collaboration.active"); } @Override public boolean isHomeExaminationSupported() { - return config.getBoolean("sitnet.byod.home.active"); + return config.getBoolean("exam.byod.home.active"); } @Override public boolean isSebExaminationSupported() { - return config.getBoolean("sitnet.byod.seb.active"); + return config.getBoolean("exam.byod.seb.active"); } @Override public boolean isCourseSearchActive() { - return config.getBoolean("sitnet.integration.courseUnitInfo.active"); + return config.getBoolean("exam.integration.courseUnitInfo.active"); } @Override public Map getCourseIntegrationUrls() { - Config urls = config.getConfig("sitnet.integration.courseUnitInfo.url"); + Config urls = config.getConfig("exam.integration.courseUnitInfo.url"); return urls.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().render())); } @Override public DateTime getExamExpirationDate(DateTime timeOfSubmission) { - String expiresAfter = config.getString("sitnet.exam.expiration.period"); + String expiresAfter = config.getString("exam.exam.expiration.period"); Period period = Period.parse(expiresAfter); return timeOfSubmission.plus(period); } @Override public DateTime getCourseValidityDate(DateTime startDate) { - String window = config.getString("sitnet.integration.courseUnitInfo.window"); + String window = config.getString("exam.integration.courseUnitInfo.window"); Period period = Period.parse(window); return startDate.minus(period); } @Override public String getExamExpirationPeriod() { - return config.getString("sitnet.exam.expiration.period"); + return config.getString("exam.exam.expiration.period"); } @Override public boolean isMaturitySupported() { - return ( - Ebean - .find(ExamExecutionType.class) - .where() - .eq("type", ExamExecutionType.Type.MATURITY.toString()) - .findCount() == - 1 - ); + return DB + .find(ExamExecutionType.class) + .where() + .eq("type", ExamExecutionType.Type.MATURITY.toString()) + .findOneOrEmpty() + .isPresent(); } @Override public boolean isPrintoutSupported() { - return ( - Ebean - .find(ExamExecutionType.class) - .where() - .eq("type", ExamExecutionType.Type.PRINTOUT.toString()) - .findCount() == - 1 - ); + return DB + .find(ExamExecutionType.class) + .where() + .eq("type", ExamExecutionType.Type.PRINTOUT.toString()) + .findOneOrEmpty() + .isPresent(); } @Override @@ -181,104 +170,104 @@ public String getAppVersion() { @Override public boolean isAnonymousReviewEnabled() { - return config.getBoolean("sitnet.exam.anonymousReview"); + return config.getBoolean("exam.exam.anonymousReview"); } @Override public String getQuitExaminationLink() { - return config.getString("sitnet.exam.seb.quitLink"); + return config.getString("exam.exam.seb.quitLink"); } @Override public String getExaminationAdminPassword() { - return config.getBoolean("sitnet.exam.seb.adminPwd.randomize") + return config.getBoolean("exam.exam.seb.adminPwd.randomize") ? UUID.randomUUID().toString() - : config.getString("sitnet.exam.seb.adminPwd.value"); + : config.getString("exam.exam.seb.adminPwd.value"); } @Override public String getSettingsPasswordEncryptionKey() { - return config.getString("sitnet.exam.seb.settingsPwd.encryption.key"); + return config.getString("exam.exam.seb.settingsPwd.encryption.key"); } @Override - public String getQuitPassword() { - return config.getString("sitnet.exam.seb.quitPwd"); + public String getHomeOrganisationRef() { + return config.getString("exam.integration.iop.organisationRef"); } @Override - public String getHomeOrganisationRef() { - return config.getString("sitnet.integration.iop.organisationRef"); + public Integer getMaxByodExaminationParticipantCount() { + return config.getInt("exam.byod.maxConcurrentParticipants"); } @Override - public Integer getMaxByodExaminationParticipantCount() { - return config.getInt("sitnet.byod.maxConcurrentParticipants"); + public boolean isByodExamCreationPermissionGrantedForNewUsers() { + return config.getBoolean("exam.byod.permission.allowed"); } @Override public String getCourseCodePrefix() { - return config.getString("sitnet.course.code.prefix"); + return config.getString("exam.course.code.prefix"); } @Override public String getIopHost() { - return config.getString("sitnet.integration.iop.host"); + return config.getString("exam.integration.iop.host"); } @Override public boolean isApiKeyUsed() { - return config.getBoolean("sitnet.integration.apiKey.enabled"); + return config.getBoolean("exam.integration.apiKey.enabled"); } @Override public String getApiKeyName() { - return config.getString("sitnet.integration.apiKey.name"); + return config.getString("exam.integration.apiKey.name"); } @Override public String getApiKeyValue() { - return config.getString("sitnet.integration.apiKey.value"); + return config.getString("exam.integration.apiKey.value"); } @Override public String getPermissionCheckUserIdentifier() { - return config.getString("sitnet.integration.enrolmentPermissionCheck.id"); + return config.getString("exam.integration.enrolmentPermissionCheck.id"); } @Override public String getPermissionCheckUrl() { - return config.getString("sitnet.integration.enrolmentPermissionCheck.url"); + return config.getString("exam.integration.enrolmentPermissionCheck.url"); } @Override public String getBaseSystemUrl() { - return config.getString("sitnet.baseSystemURL"); + return config.getString("exam.baseSystemURL"); } @Override public String getSystemAccount() { - return config.getString("sitnet.email.system.account"); + return config.getString("exam.email.system.account"); } @Override public String getAttachmentPath() { - return config.getString("sitnet.attachments.path"); + return config.getString("exam.attachments.path"); } @Override public String getLoginType() { - return config.getString("sitnet.login"); + return config.getString("exam.login"); } @Override public boolean isMultiStudentIdEnabled() { - return config.getBoolean("sitnet.user.studentIds.multiple.enabled"); + return config.getBoolean("exam.user.studentIds.multiple.enabled"); } @Override public String getMultiStudentOrganisations() { - return config.getString("sitnet.user.studentIds.multiple.organisations"); + return config.getString("exam.user.studentIds.multiple.organisations"); } @Override @@ -286,6 +275,11 @@ public String getCsrfCookie() { return config.getString("play.filters.csrf.cookie.name"); } + @Override + public List getSupportedLanguages() { + return config.getStringList("play.i18n.langs"); + } + @Override public boolean hasPath(String path) { return config.hasPath(path); diff --git a/app/util/csv/CsvBuilderImpl.java b/app/util/csv/CsvBuilderImpl.java index 7d09cea39d..101fba69ad 100644 --- a/app/util/csv/CsvBuilderImpl.java +++ b/app/util/csv/CsvBuilderImpl.java @@ -23,7 +23,7 @@ import com.opencsv.CSVReaderBuilder; import com.opencsv.CSVWriter; import com.opencsv.exceptions.CsvException; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.ExpressionList; import java.io.File; import java.io.FileReader; @@ -47,17 +47,18 @@ import org.joda.time.format.DateTimeFormatter; import org.jsoup.Jsoup; import org.jsoup.safety.Safelist; -import play.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CsvBuilderImpl implements CsvBuilder { - private static final Logger.ALogger logger = Logger.of(CsvBuilderImpl.class); + private final Logger logger = LoggerFactory.getLogger(CsvBuilderImpl.class); @Override public File build(Long startDate, Long endDate) throws IOException { Date start = new Date(startDate); Date end = new Date(endDate); - List examRecords = Ebean + List examRecords = DB .find(ExamRecord.class) .fetch("examScore") .where() @@ -76,7 +77,7 @@ public File build(Long startDate, Long endDate) throws IOException { @Override public File build(Long examId, Collection childIds) throws IOException { - List examRecords = Ebean + List examRecords = DB .find(ExamRecord.class) .fetch("examScore") .where() @@ -157,7 +158,7 @@ public void parseGrades(File csvFile, User user, Role.Name role) throws IOExcept logger.warn("Invalid input, unable to grade"); continue; } - ExpressionList el = Ebean + ExpressionList el = DB .find(Exam.class) .where() .idEq(examId) @@ -176,22 +177,17 @@ public void parseGrades(File csvFile, User user, Role.Name role) throws IOExcept } String gradeName = records[1]; GradeScale scale = exam.getGradeScale() == null ? exam.getCourse().getGradeScale() : exam.getGradeScale(); - List grades = Ebean - .find(Grade.class) - .where() - .eq("name", gradeName) - .eq("gradeScale", scale) - .findList(); + List grades = DB.find(Grade.class).where().eq("name", gradeName).eq("gradeScale", scale).findList(); if (grades.isEmpty()) { logger.warn("No grade found with name {}", gradeName); } else if (grades.size() > 1) { logger.warn("Multiple grades found with name {}", gradeName); } else { - exam.setGrade(grades.get(0)); + exam.setGrade(grades.getFirst()); exam.setGradedByUser(user); exam.setGradedTime(DateTime.now()); exam.setState(Exam.State.GRADED); - exam.setAnswerLanguage(exam.getExamLanguages().get(0).getCode()); + exam.setAnswerLanguage(exam.getExamLanguages().getFirst().getCode()); exam.setCreditType(exam.getExamType()); String feedback = records.length > 2 ? records[2] : null; if (feedback != null && !feedback.isEmpty()) { diff --git a/app/util/datetime/DateTimeHandler.java b/app/util/datetime/DateTimeHandler.java index 70a80cfb18..f97652ec4e 100644 --- a/app/util/datetime/DateTimeHandler.java +++ b/app/util/datetime/DateTimeHandler.java @@ -67,5 +67,6 @@ List getExceptionEvents( DateTime normalize(DateTime dateTime, DateTimeZone dtz); List getDefaultWorkingHours(LocalDate date, ExamRoom room); int getTimezoneOffset(LocalDate date, ExamRoom room); + int getTimezoneOffset(DateTime date); List getWorkingHoursForDate(LocalDate date, ExamRoom room); } diff --git a/app/util/datetime/DateTimeHandlerImpl.java b/app/util/datetime/DateTimeHandlerImpl.java index 993a7572bc..406d8d9ee3 100644 --- a/app/util/datetime/DateTimeHandlerImpl.java +++ b/app/util/datetime/DateTimeHandlerImpl.java @@ -21,7 +21,6 @@ import java.util.Comparator; import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; import models.ExamRoom; @@ -33,8 +32,6 @@ import org.joda.time.DateTimeZone; import org.joda.time.Interval; import org.joda.time.LocalDate; -import org.joda.time.LocalTime; -import org.joda.time.base.AbstractInterval; import util.config.ConfigReader; public class DateTimeHandlerImpl implements DateTimeHandler { @@ -58,8 +55,8 @@ public List findGaps(List reserved, Interval searchInterval) // create a sub-list that excludes interval which does not overlap with // searchInterval List subReservedList = removeNonOverlappingIntervals(reserved, searchInterval); - DateTime subEarliestStart = subReservedList.get(0).getStart(); - DateTime subLatestEnd = subReservedList.get(subReservedList.size() - 1).getEnd(); + DateTime subEarliestStart = subReservedList.getFirst().getStart(); + DateTime subLatestEnd = subReservedList.getLast().getEnd(); // in case the searchInterval is wider than the union of the existing // include searchInterval.start => earliestExisting.start @@ -79,7 +76,7 @@ public List findGaps(List reserved, Interval searchInterval) private List getExistingIntervalGaps(List reserved) { List gaps = new ArrayList<>(); - Interval current = reserved.get(0); + Interval current = reserved.getFirst(); for (int i = 1; i < reserved.size(); i++) { Interval next = reserved.get(i); Interval gap = current.gap(next); @@ -92,12 +89,12 @@ private List getExistingIntervalGaps(List reserved) { } private List removeNonOverlappingIntervals(List reserved, Interval searchInterval) { - return reserved.stream().filter(interval -> interval.overlaps(searchInterval)).collect(Collectors.toList()); + return reserved.stream().filter(interval -> interval.overlaps(searchInterval)).toList(); } private boolean hasNoOverlap(List reserved, DateTime searchStart, DateTime searchEnd) { - DateTime earliestStart = reserved.get(0).getStart(); - DateTime latestStop = reserved.get(reserved.size() - 1).getEnd(); + DateTime earliestStart = reserved.getFirst().getStart(); + DateTime latestStop = reserved.getLast().getEnd(); return (!searchEnd.isAfter(earliestStart) || !searchStart.isBefore(latestStop)); } @@ -117,13 +114,25 @@ public List getExceptionEvents( DateTime end = new DateTime(ewh.getEndDate()).plusMillis(ewh.getEndDateTimezoneOffset()); Interval exception = new Interval(start, end); Interval wholeDay = date.toInterval(); + // exception covers this day fully if (exception.contains(wholeDay) || exception.equals(wholeDay)) { exceptions.clear(); exceptions.add(wholeDay); - break; - } - if (exception.overlaps(wholeDay)) { - exceptions.add(new Interval(exception.getStart(), exception.getEnd())); + } else if (exception.overlaps(wholeDay)) { + // exception starts this day but ends on a later day + if (start.toLocalDate().equals(date) && end.toLocalDate().isAfter(date)) { + exceptions.add(new Interval(exception.getStart(), wholeDay.getEnd())); + } + // exception ends this day but starts on an earlier day + else if (start.toLocalDate().isBefore(date) && end.toLocalDate().equals(date)) { + exceptions.add(new Interval(wholeDay.getStart(), exception.getEnd())); + } + // exception starts and ends this day + else { + exceptions.add( + new Interval(exception.getStart().withDate(date), exception.getEnd().withDate(date)) + ); + } } } } @@ -131,14 +140,16 @@ public List getExceptionEvents( } @Override - public List mergeSlots(List slots) { - if (slots.size() <= 1) { - return slots; + public List mergeSlots(List intervals) { + if (intervals.size() <= 1) { + return intervals; } - slots.sort(Comparator.comparing(AbstractInterval::getStart)); + // make sure the list is mutable, otherwise sorting fails + var slots = new ArrayList<>(intervals); + slots.sort(Comparator.comparing(Interval::getStart)); boolean isMerged = false; List merged = new ArrayList<>(); - merged.add(slots.get(0)); + merged.add(slots.getFirst()); for (int i = 1; i < slots.size(); ++i) { Interval first = slots.get(i - 1); Interval second = slots.get(i); @@ -256,6 +267,11 @@ public int getTimezoneOffset(LocalDate date, ExamRoom room) { return 0; } + @Override + public int getTimezoneOffset(DateTime date) { + return configReader.getDefaultTimeZone().getOffset(date); + } + @Override public List getWorkingHoursForDate(LocalDate date, ExamRoom room) { List workingHours = getDefaultWorkingHours(date, room); @@ -268,24 +284,11 @@ public List getWorkingHoursForDate(LocalDate date, ExamRoom room) List availableHours = new ArrayList<>(); if (!extensionEvents.isEmpty()) { List unifiedIntervals = mergeSlots( - Stream - .concat(workingHours.stream().map(OpeningHours::getHours), extensionEvents.stream()) - .collect(Collectors.toList()) + Stream.concat(workingHours.stream().map(OpeningHours::getHours), extensionEvents.stream()).toList() ); - int tzOffset; - if (workingHours.isEmpty()) { - LocalTime lt = LocalTime.now().withHourOfDay(java.time.LocalTime.NOON.getHour()); - tzOffset = DateTimeZone.forID(room.getLocalTimezone()).getOffset(date.toDateTime(lt)); - } else { - tzOffset = workingHours.get(0).getTimezoneOffset(); - } + int offset = DateTimeZone.forID(room.getLocalTimezone()).getOffset(DateTime.now().withDayOfYear(1)); workingHours.clear(); - workingHours.addAll( - unifiedIntervals - .stream() - .map(interval -> new OpeningHours(interval, tzOffset)) - .collect(Collectors.toList()) - ); + workingHours.addAll(unifiedIntervals.stream().map(interval -> new OpeningHours(interval, offset)).toList()); } if (!restrictionEvents.isEmpty()) { for (OpeningHours hours : workingHours) { diff --git a/app/util/excel/ExcelBuilderImpl.java b/app/util/excel/ExcelBuilderImpl.java index d74ea9ae09..dc533a7384 100644 --- a/app/util/excel/ExcelBuilderImpl.java +++ b/app/util/excel/ExcelBuilderImpl.java @@ -1,6 +1,6 @@ package util.excel; -import io.ebean.Ebean; +import io.ebean.DB; import io.vavr.Tuple; import io.vavr.Tuple2; import java.io.ByteArrayOutputStream; @@ -121,7 +121,7 @@ private void appendCellsToRow(Row row, List> cells) { @Override public ByteArrayOutputStream build(Long examId, Collection childIds) throws IOException { - List examRecords = Ebean + List examRecords = DB .find(ExamRecord.class) .fetch("examScore") .where() @@ -177,27 +177,20 @@ public ByteArrayOutputStream buildStudentReport(Exam exam, User student, Message appendCell(valueRow, value); } int questionNumber; - for (ExamSection es : exam.getExamSections().stream().sorted().collect(Collectors.toList())) { + for (ExamSection es : exam.getExamSections().stream().sorted().toList()) { questionNumber = 1; - for (ExamSectionQuestion esq : es.getSectionQuestions().stream().sorted().collect(Collectors.toList())) { - String questionType = ""; - switch (esq.getQuestion().getType()) { - case EssayQuestion: - questionType = messages.get(lang, "reports.question.type.essay"); - break; - case ClozeTestQuestion: - questionType = messages.get(lang, "reports.question.type.cloze"); - break; - case MultipleChoiceQuestion: - questionType = messages.get(lang, "reports.question.type.multiplechoice"); - break; - case WeightedMultipleChoiceQuestion: - questionType = messages.get(lang, "reports.question.type.weightedmultiplechoide"); - break; - case ClaimChoiceQuestion: - questionType = messages.get(lang, "reports.question.type.claim"); - break; - } + for (ExamSectionQuestion esq : es.getSectionQuestions().stream().sorted().toList()) { + String questionType = + switch (esq.getQuestion().getType()) { + case EssayQuestion -> messages.get(lang, "reports.question.type.essay"); + case ClozeTestQuestion -> messages.get(lang, "reports.question.type.cloze"); + case MultipleChoiceQuestion -> messages.get(lang, "reports.question.type.multiplechoice"); + case WeightedMultipleChoiceQuestion -> messages.get( + lang, + "reports.question.type.weightedmultiplechoide" + ); + case ClaimChoiceQuestion -> messages.get(lang, "reports.question.type.claim"); + }; appendCell( headerRow, @@ -237,14 +230,17 @@ public ByteArrayOutputStream buildScoreExcel(Long examId, Collection child linkFont.setUnderline(HSSFFont.U_SINGLE); linkStyle.setFont(linkFont); - Exam parentExam = Ebean + Optional parentExamOption = DB .find(Exam.class) .fetch("examSections.sectionQuestions.question") .where() .eq("id", examId) - .findOne(); - - List childExams = Ebean + .findOneOrEmpty(); + if (parentExamOption.isEmpty()) { + throw new RuntimeException("parent exam not found"); + } + Exam parentExam = parentExamOption.get(); + List childExams = DB .find(Exam.class) .fetch("examParticipation.user") .fetch("examSections.sectionQuestions.question") @@ -344,7 +340,7 @@ public ByteArrayOutputStream buildScoreExcel(Long examId, Collection child exam.getState() == Exam.State.GRADED_LOGGED || exam.getState() == Exam.State.ARCHIVED; - /* Get non-score cells and append them to a new excel row */ + /* Get non-score cells and append them to a new Excel row */ List> defaultCells = getScoreReportDefaultCells(student, exam, examScore); Row currentRow = sheet.createRow(sheet.getLastRowNum() + 1); appendCellsToRow(currentRow, defaultCells); diff --git a/app/util/file/ChunkMaker.java b/app/util/file/ChunkMaker.java index a685f31a1f..812acfdff6 100644 --- a/app/util/file/ChunkMaker.java +++ b/app/util/file/ChunkMaker.java @@ -16,15 +16,15 @@ package util.file; -import akka.stream.Attributes; -import akka.stream.FlowShape; -import akka.stream.Inlet; -import akka.stream.Outlet; -import akka.stream.stage.AbstractInHandler; -import akka.stream.stage.AbstractOutHandler; -import akka.stream.stage.GraphStage; -import akka.stream.stage.GraphStageLogic; -import akka.util.ByteString; +import org.apache.pekko.stream.Attributes; +import org.apache.pekko.stream.FlowShape; +import org.apache.pekko.stream.Inlet; +import org.apache.pekko.stream.Outlet; +import org.apache.pekko.stream.stage.AbstractInHandler; +import org.apache.pekko.stream.stage.AbstractOutHandler; +import org.apache.pekko.stream.stage.GraphStage; +import org.apache.pekko.stream.stage.GraphStageLogic; +import org.apache.pekko.util.ByteString; import scala.Tuple2; public class ChunkMaker extends GraphStage> { @@ -33,7 +33,7 @@ public class ChunkMaker extends GraphStage> { public Inlet in = Inlet.create("ChunkMaker.in"); public Outlet out = Outlet.create("ChunkMaker.out"); - private FlowShape shape = FlowShape.of(in, out); + private final FlowShape shape = FlowShape.of(in, out); public ChunkMaker(int chunkSize) { this.chunkSize = chunkSize; diff --git a/app/util/file/FileHandlerImpl.java b/app/util/file/FileHandlerImpl.java index c603498a5e..8f3a94a9e9 100644 --- a/app/util/file/FileHandlerImpl.java +++ b/app/util/file/FileHandlerImpl.java @@ -1,6 +1,6 @@ package util.file; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -17,8 +17,9 @@ import javax.validation.constraints.NotNull; import models.Attachment; import models.api.AttachmentContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.Environment; -import play.Logger; import play.libs.Files; import play.mvc.Http; import util.config.ConfigReader; @@ -26,7 +27,7 @@ public class FileHandlerImpl implements FileHandler { private static final int KB = 1024; - private static final Logger.ALogger logger = Logger.of(FileHandlerImpl.class); + private final Logger logger = LoggerFactory.getLogger(FileHandlerImpl.class); private final Environment environment; private final ConfigReader configReader; @@ -111,10 +112,10 @@ public void removeAttachmentFile(String filePath) { Path path = FileSystems.getDefault().getPath(filePath); try { if (!java.nio.file.Files.deleteIfExists(path)) { - logger.error("Could not delete " + path + " because it does not exist."); + logger.error("Could not delete {} because it does not exist.", path); } } catch (IOException e) { - e.printStackTrace(); + logger.error("IO Exception occurred", e); } } @@ -127,7 +128,7 @@ public void removePrevious(AttachmentContainer container) { container.save(); a.delete(); // Remove the file from disk if no references to it are found - boolean removeFromDisk = Ebean.find(Attachment.class).where().eq("filePath", filePath).findList().isEmpty(); + boolean removeFromDisk = DB.find(Attachment.class).where().eq("filePath", filePath).findList().isEmpty(); if (removeFromDisk) { removeAttachmentFile(a.getFilePath()); } diff --git a/app/util/json/JsonDeserializer.java b/app/util/json/JsonDeserializer.java deleted file mode 100644 index a98097c0a2..0000000000 --- a/app/util/json/JsonDeserializer.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ - -package util.json; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import java.lang.reflect.Type; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; -import play.Logger; - -public final class JsonDeserializer { - - private static final Logger.ALogger logger = Logger.of(JsonDeserializer.class); - - private JsonDeserializer() {} - - private static final GsonBuilder gsonBuilder = new GsonBuilder(); - - static { - gsonBuilder.registerTypeAdapter(Date.class, new DateDeserializer()); - gsonBuilder.registerTypeAdapter(DateTime.class, new DateTimeDeserializer()); - } - - private static final Gson gson = gsonBuilder.create(); - - private static class DateDeserializer implements com.google.gson.JsonDeserializer { - - @Override - public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { - try { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(json.getAsString()); - } catch (ParseException e) { - try { - return new Date(json.getAsLong()); - } catch (RuntimeException e2) { - logger.warn("Failed to parse date " + json.getAsString()); - } - } - return null; - } - } - - private static class DateTimeDeserializer implements com.google.gson.JsonDeserializer { - - @Override - public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { - try { - return ISODateTimeFormat.dateTime().parseDateTime(json.getAsString()); - } catch (IllegalArgumentException e) { - try { - return new DateTime(json.getAsLong()); - } catch (RuntimeException e2) { - logger.warn("Failed to parse date " + json.getAsString()); - } - } - return null; - } - } - - public static T deserialize(Class model, JsonNode node) { - return gson.fromJson(node.toString(), model); - } -} diff --git a/app/util/json/JsonDeserializer.scala b/app/util/json/JsonDeserializer.scala new file mode 100644 index 0000000000..28badab3a7 --- /dev/null +++ b/app/util/json/JsonDeserializer.scala @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and limitations under the Licence. + */ + +package util.json + +import com.fasterxml.jackson.databind.JsonNode +import com.google.gson.GsonBuilder +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import org.joda.time.DateTime +import org.joda.time.format.ISODateTimeFormat +import play.api.Logging + +import java.lang.reflect.Type +import java.text.SimpleDateFormat +import java.util.Date +import scala.util.{Success, Try} + +object JsonDeserializer: + private val builder = new GsonBuilder() + builder.registerTypeAdapter(classOf[Date], new DateDeserializer()) + builder.registerTypeAdapter(classOf[DateTime], new DateTimeDeserializer()) + private val gson = builder.create() + + def deserialize[T](model: Class[T], node: JsonNode): T = gson.fromJson(node.toString, model) + +class DateDeserializer extends JsonDeserializer[Date] with Logging: + override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Date = + Try(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(json.getAsString)) match + case Success(d) => d + case _ => + Try(new Date(json.getAsLong)) match + case Success(dt) => dt + case _ => + Try(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").parse(json.getAsString)) match + case Success(dt) => dt + case _ => + logger.warn(s"Failed to parse date ${json.getAsString}") + null + +class DateTimeDeserializer extends JsonDeserializer[DateTime] with Logging: + override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): DateTime = + Try(ISODateTimeFormat.dateTime().parseDateTime(json.getAsString)) match + case Success(dt) => dt + case _ => + Try(new DateTime(json.getAsLong)) match + case Success(dt) => dt + case _ => + logger.warn(s"Failed to parse datetime ${json.getAsString}") + null diff --git a/app/util/json/JsonFilter.java b/app/util/json/JsonFilter.java deleted file mode 100644 index a0de3a0cf9..0000000000 --- a/app/util/json/JsonFilter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 Exam Consortium - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - * - */ - -package util.json; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.util.Set; - -public class JsonFilter { - - public static void filterProperties(JsonNode node, boolean isRoot, Set ids, String... properties) { - if (isRoot && !ids.isEmpty() && node.has("id")) { - final long id = node.get("id").asLong(); - if (!ids.contains(id)) { - return; - } - } - for (String prop : properties) { - if (node.has(prop) && node.isObject()) { - ((ObjectNode) node).remove(prop); - } - } - for (JsonNode child : node) { - filterProperties(child, node.isArray() && isRoot, ids, properties); - } - } -} diff --git a/ui/src/app/dashboard/staff/admin/admin-dashboard.module.ts b/app/util/json/JsonFilter.scala similarity index 55% rename from ui/src/app/dashboard/staff/admin/admin-dashboard.module.ts rename to app/util/json/JsonFilter.scala index 96e110eaf2..5b1894fd63 100644 --- a/ui/src/app/dashboard/staff/admin/admin-dashboard.module.ts +++ b/app/util/json/JsonFilter.scala @@ -11,16 +11,22 @@ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. + * */ -// TODO: maybe this module is redundant. Let's keep it anyway in case we want to lazy load admin stuff in the future -import { NgModule } from '@angular/core'; -import { ReservationModule } from '../../../reservation/reservation.module'; -import { SharedModule } from '../../../shared/shared.module'; -import { AdminDashboardComponent } from './admin-dashboard.component'; -@NgModule({ - imports: [SharedModule, ReservationModule], - exports: [AdminDashboardComponent], - declarations: [AdminDashboardComponent], -}) -export class AdminDashboardModule {} +package util.json + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.ObjectNode + +import scala.jdk.CollectionConverters._ + +object JsonFilter: + // TODO: make immutable + def filterProperties(node: JsonNode, ids: Set[Long], properties: String*): Unit = + def helper(acc: JsonNode): Unit = + if ids.isEmpty || !acc.has("id") || ids.contains(acc.get("id").asLong) then + (if acc.isObject then acc.asInstanceOf[ObjectNode].remove(properties.asJava) else acc).elements.asScala + .foreach(helper) + + helper(node) diff --git a/app/util/scala/Binders.scala b/app/util/scala/Binders.scala index 68c1863575..bf07b0e425 100644 --- a/app/util/scala/Binders.scala +++ b/app/util/scala/Binders.scala @@ -15,9 +15,6 @@ package util.scala -object Binders { - +object Binders: type LongList = java.util.List[java.lang.Long] type IntList = java.util.List[java.lang.Integer] - -} diff --git a/app/util/scala/DbApiHelper.scala b/app/util/scala/DbApiHelper.scala new file mode 100644 index 0000000000..3860799c7f --- /dev/null +++ b/app/util/scala/DbApiHelper.scala @@ -0,0 +1,29 @@ +/* + * + * * Copyright (c) 2024 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) + * * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent + * * versions of the EUPL (the "Licence"); + * * You may not use this work except in compliance with the Licence. + * * You may obtain a copy of the Licence at: + * * + * * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl + * * + * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed + * * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the Licence for the specific language governing permissions and limitations under the Licence. + * + */ + +package util.scala + +import io.ebean.{ExpressionList, Model} + +import scala.jdk.CollectionConverters._ +import scala.jdk.OptionConverters._ + +trait DbApiHelper: + extension [T <: Model](el: ExpressionList[T]) + def find: Option[T] = el.findOneOrEmpty().toScala + def list: List[T] = el.findList().asScala.toList + def distinct: Set[T] = el.findSet().asScala.toSet diff --git a/app/util/scala/JavaJsonResultProducer.scala b/app/util/scala/JavaApiHelper.scala similarity index 65% rename from app/util/scala/JavaJsonResultProducer.scala rename to app/util/scala/JavaApiHelper.scala index 1fce206e7e..b1eada69a1 100644 --- a/app/util/scala/JavaJsonResultProducer.scala +++ b/app/util/scala/JavaApiHelper.scala @@ -17,18 +17,12 @@ package util.scala import io.ebean.Model import play.api.mvc.{InjectedController, Result} -import play.libs.{Json => JavaJson} +import play.api.mvc.Results.Status +import play.libs.Json as JavaJson -import scala.jdk.CollectionConverters._ +trait JavaApiHelper: -trait JavaJsonResultProducer { - self: InjectedController => + extension [T <: Model](model: T) def toResult(status: Status): Result = status(JavaJson.toJson(model).toString) - implicit class JavaModelToResult[T <: Model](model: T) { - def toResult(status: Int): Result = Status(status)(JavaJson.toJson(model).toString) - } - implicit class JavaModelsToResult[T <: Model](model: Iterable[T]) { - def toResult(status: Int): Result = Status(status)(JavaJson.toJson(model.asJava).toString) - } - -} + extension [T <: Model](model: Iterable[T]) + def toResult(status: Status): Result = status(JavaJson.toJson(model).toString) diff --git a/app/util/xml/MoodleXmlExporter.scala b/app/util/xml/MoodleXmlExporter.scala index a63d181977..3f6553cbf9 100644 --- a/app/util/xml/MoodleXmlExporter.scala +++ b/app/util/xml/MoodleXmlExporter.scala @@ -2,6 +2,5 @@ package util.xml import models.questions.Question -trait MoodleXmlExporter { +trait MoodleXmlExporter: def convert(questions: Seq[Question]): String -} diff --git a/app/util/xml/MoodleXmlExporterImpl.scala b/app/util/xml/MoodleXmlExporterImpl.scala index 149adb0fe3..fa49ab7067 100644 --- a/app/util/xml/MoodleXmlExporterImpl.scala +++ b/app/util/xml/MoodleXmlExporterImpl.scala @@ -1,43 +1,42 @@ package util.xml -import java.io.File -import java.nio.file.Files -import java.util.Base64 import models.Tag import models.questions.{MultipleChoiceOption, Question} import org.jsoup.Jsoup +import java.io.File +import java.nio.file.Files +import java.util.Base64 import scala.io.Source import scala.jdk.CollectionConverters._ import scala.xml._ import scala.xml.parsing.ConstructingParser -class MoodleXmlExporterImpl extends MoodleXmlExporter { +class MoodleXmlExporterImpl extends MoodleXmlExporter: - private def moodleType(question: Question): String = question.getType.toString match { + private def moodleType(question: Question): String = question.getType.toString match case "EssayQuestion" => "essay" case "ClozeTestQuestion" => "cloze" case _ => "multichoice" - } private def Essay: Node = - private def convertMultiChoiceOption(option: MultipleChoiceOption): Node = { - val fraction = if (option.isCorrectOption) 100 else 0 + private def convertMultiChoiceOption(option: MultipleChoiceOption): Node = + val fraction = if option.isCorrectOption then 100 else 0 {option.getOption} - } - private def convertWeightedMultiChoiceOption(option: MultipleChoiceOption, - maxScore: Double): Node = { + private def convertWeightedMultiChoiceOption( + option: MultipleChoiceOption, + maxScore: Double + ): Node = val fraction = option.getDefaultScore / maxScore * 100 {option.getOption} - } - private def convertByType(question: Question): NodeBuffer = question.getType.toString match { + private def convertByType(question: Question): NodeBuffer = question.getType.toString match case "MultipleChoiceQuestion" => val config = 1 @@ -50,14 +49,13 @@ class MoodleXmlExporterImpl extends MoodleXmlExporter { 1 false none - val options = question.getOptions.asScala.map(o => - convertWeightedMultiChoiceOption(o, question.getMaxDefaultScore)) + val options = + question.getOptions.asScala.map(o => convertWeightedMultiChoiceOption(o, question.getMaxDefaultScore)) config ++= options case "EssayQuestion" => - val criteria = question.getDefaultEvaluationCriteria match { + val criteria = question.getDefaultEvaluationCriteria match case ec if isEmpty(ec) => PCData("") case ec => PCData(ec) - } val config = @@ -66,7 +64,6 @@ class MoodleXmlExporterImpl extends MoodleXmlExporter { 1 config ++= Essay - } private def stripHtml(html: String): String = Jsoup.parse(html).text @@ -75,11 +72,11 @@ class MoodleXmlExporterImpl extends MoodleXmlExporter { private def convert(tag: Tag): Node = {tag.getName} private def maxScore(question: Question): Double = - if (question.getDefaultEvaluationType == Question.EvaluationType.Selection) 1 + if question.getDefaultEvaluationType == Question.EvaluationType.Selection then 1 else question.getMaxDefaultScore() private def attachment(question: Question): Option[(String, Node)] = - question.getAttachment match { + question.getAttachment match case null => None case a => val file = new File(a.getFilePath) @@ -89,18 +86,15 @@ class MoodleXmlExporterImpl extends MoodleXmlExporter { val ref = s"""
Attachment: ${filename.toUpperCase}""" Some(ref, {b64}) - } - private def convert(question: Question): Node = { + private def convert(question: Question): Node = val text = question.getQuestion.replace(" class=\"math-tex\"", "") - val instructions = question.getDefaultAnswerInstructions match { + val instructions = question.getDefaultAnswerInstructions match case i if isEmpty(i) => "" case i => s"
Answer instructions: $i" - } - val wc = question.getDefaultExpectedWordCount match { + val wc = question.getDefaultExpectedWordCount match case null => "" case c => s"
Expected word count: $c" - } val att = attachment(question) val ref = att.map(_._1).getOrElse("") val questionText = s"$text $instructions $wc $ref" @@ -121,9 +115,8 @@ class MoodleXmlExporterImpl extends MoodleXmlExporter { {convertByType(question)}
- } - def convert(questions: Seq[Question]): String = { + def convert(questions: Seq[Question]): String = val quiz: Node = {questions.map(convert)} @@ -137,6 +130,3 @@ class MoodleXmlExporterImpl extends MoodleXmlExporter { XML.write(writer, doc, "utf-8", xmlDecl = true, doctype = null) writer.close() writer.toString - } - -} diff --git a/app/util/xml/MoodleXmlImporter.scala b/app/util/xml/MoodleXmlImporter.scala index 371cab4e11..940a2b1ad3 100644 --- a/app/util/xml/MoodleXmlImporter.scala +++ b/app/util/xml/MoodleXmlImporter.scala @@ -3,6 +3,5 @@ package util.xml import models.User import models.questions.Question -trait MoodleXmlImporter { +trait MoodleXmlImporter: def convert(questions: String, user: User): Seq[Question] -} diff --git a/app/util/xml/MoodleXmlImporterImpl.scala b/app/util/xml/MoodleXmlImporterImpl.scala index 355cad7bb7..361bf830fb 100644 --- a/app/util/xml/MoodleXmlImporterImpl.scala +++ b/app/util/xml/MoodleXmlImporterImpl.scala @@ -1,13 +1,13 @@ package util.xml -import io.ebean.Ebean +import io.ebean.DB import models.questions.{MultipleChoiceOption, Question} import models.{Attachment, Tag, User} import org.apache.commons.compress.archivers.tar.{TarArchiveEntry, TarArchiveOutputStream} import org.apache.commons.compress.compressors.CompressorStreamFactory import org.jsoup.Jsoup import org.jsoup.nodes.{Element, TextNode} -import play.api.Logger +import play.api.Logging import util.file.FileHandler import java.io.{BufferedOutputStream, File} @@ -16,52 +16,47 @@ import java.util.Base64 import javax.inject.Inject import scala.xml._ -class MoodleXmlImporterImpl @Inject()(fileHandler: FileHandler) extends MoodleXmlImporter { +class MoodleXmlImporterImpl @Inject() (fileHandler: FileHandler) extends MoodleXmlImporter with Logging: import scala.jdk.CollectionConverters._ import scala.jdk.StreamConverters._ - private val logger = Logger(this.getClass).logger - private def tags(src: Node, user: User): Seq[Tag] = (src \\ "tag" \ "text") .map(_.text) - .map(text => { - val userTags = Ebean + .map(text => + val userTags = DB .find(classOf[Tag]) .where .eq("name", text) .eq("creator", user) .findList .asScala - userTags.toList match { + userTags.toList match case h :: _ => h case _ => val t = new Tag - t.setName(text) + t.setName(text.toLowerCase) t.setCreator(user) t - } - }) + ) - private def copyFile(srcFile: Path, id: Long) = { + private def copyFile(srcFile: Path, id: Long) = val newFilePath = fileHandler.createFilePath("question", id.toString) fileHandler.copyFile(srcFile, new File(newFilePath)) newFilePath - } - private def files(src: Node) = { - (src \\ "file").map(n => { + private def files(src: Node) = + (src \\ "file").map(n => val (name, data) = (n \@ "name", n.text) val bytes = Base64.getDecoder.decode(data) val ct = Files.probeContentType(Path.of(name)) val file = Files.createTempFile("moodle-attachment", ".tmp") Files.write(file, bytes) (ct, file, name) - }) - } + ) - private def zip(files: Seq[(String, Path, String)]) = { + private def zip(files: Seq[(String, Path, String)]) = val tarball = File.createTempFile("moodle-attachments", ".tar.gz").toPath val out = Files.newOutputStream(tarball) val bufOut = new BufferedOutputStream(out) @@ -70,157 +65,143 @@ class MoodleXmlImporterImpl @Inject()(fileHandler: FileHandler) extends MoodleXm .createCompressorOutputStream(CompressorStreamFactory.GZIP, bufOut) val aos = new TarArchiveOutputStream(gzOut) aos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX) - files.foreach(file => { + files.foreach(file => val entry = new TarArchiveEntry(file._2.toFile, file._3) aos.putArchiveEntry(entry) Files.copy(file._2, aos) aos.closeArchiveEntry() - }) + ) aos.finish() aos.close() ("application/gzip", tarball, "attachments.tar.gz") - } private def attachment(src: Node, id: Long): Option[Attachment] = - files(src) match { + files(src) match case Nil => None case files => - val (ct, path, name) = if (files.length > 1) zip(files) else files.head + val (ct, path, name) = if files.length > 1 then zip(files) else files.head val newFilePath = copyFile(path, id) Some(fileHandler.createNew(name, ct, newFilePath)) - } private def parseFileName(el: Element, attr: String): String = s"[Attachment: ${el.attr(attr).dropWhile(_ != '/').tail}]" private def parseMedia(html: String, selector: String, attr: String)( - ff: Element => Boolean): String = { + ff: Element => Boolean + ): String = val doc = Jsoup.parse(html) val elements = doc.select(selector).stream.toScala(List).filter(ff) - def sourceFn: Element => Element = selector match { + def sourceFn: Element => Element = selector match case "audio" | "video" => _.select("source").first case "img" | "a" => identity - } elements.foreach(el => el.replaceWith(new TextNode(parseFileName(sourceFn(el), attr)))) doc.body.children.toString - } - private def stripAttachmentTags(src: String): String = { + private def stripAttachmentTags(src: String): String = val anchorFilter: Element => Boolean = _.attr("href").contains("@@PLUGINFILE@@") val mediaFilter: Element => Boolean = _ => true - Seq(("img", "src", mediaFilter), - ("video", "src", mediaFilter), - ("audio", "src", mediaFilter), - ("a", "href", anchorFilter)).foldLeft(src) { - case (html, (el, attr, fn)) => parseMedia(html, el, attr)(fn) + Seq( + ("img", "src", mediaFilter), + ("video", "src", mediaFilter), + ("audio", "src", mediaFilter), + ("a", "href", anchorFilter) + ).foldLeft(src) { case (html, (el, attr, fn)) => + parseMedia(html, el, attr)(fn) } - } - private def convertCommon(src: Node, user: User, mode: String): Question = { + private def convertCommon(src: Node, user: User, mode: String): Question = val srcText = src \ "questiontext" val format = srcText.head.attribute("format").get.text - val questionText = format match { + val questionText = format match case "html" => (srcText \ "text").text case _ => "

" + (srcText \ "text").text + "

" - } val question = new Question question.setQuestion(stripAttachmentTags(questionText)) question.setTags(tags(src, user).asJava) question.setCreatorWithDate(user) question.setModifierWithDate(user) question.setQuestionOwners(Set(user).asJava) - val questionType = mode match { + val questionType = mode match case "essay" => Question.Type.EssayQuestion case "multichoice" => Question.Type.MultipleChoiceQuestion case "weighted-multichoice" => Question.Type.WeightedMultipleChoiceQuestion - } question.setType(questionType) question.setState("SAVED") question.save() - attachment(src, question.getId()) match { + attachment(src, question.getId()) match case Some(a) => question.setAttachment(a) question.save() question case None => question - } - } - private def convertEssay(src: Node, user: User): Question = { + private def convertEssay(src: Node, user: User): Question = val question = convertCommon(src, user, mode = "essay") val score = (src \ "defaultgrade").text.toDouble question.setDefaultMaxScore(score) question.setDefaultEvaluationType(Question.EvaluationType.Points) question.update() question - } private def optionText(src: Node): String = - src.attribute("format").get.text match { + src.attribute("format").get.text match case "html" => Jsoup.parse((src \ "text").text).text() case _ => (src \ "text").text - } - private def convertOption(src: Node): MultipleChoiceOption = { + private def convertOption(src: Node): MultipleChoiceOption = val isCorrect = src.attribute("fraction").get.text.toInt == 100 val option = new MultipleChoiceOption option.setOption(optionText(src)) option.setCorrectOption(isCorrect) option - } - private def convertWeightedOption(src: Node, maxScore: Double): MultipleChoiceOption = { + private def convertWeightedOption(src: Node, maxScore: Double): MultipleChoiceOption = val fraction = src.attribute("fraction").get.text.toDouble val score = fraction / 100 * maxScore val option = new MultipleChoiceOption option.setOption(optionText(src)) option.setDefaultScore(score) option - } - private def convertNonWeightedMultiChoice(src: Node, question: Question): Question = { + private def convertNonWeightedMultiChoice(src: Node, question: Question): Question = // question should have a single with fraction 100, others should have fraction zero val score = (src \ "defaultgrade").text.toDouble question.setDefaultMaxScore(score) val (wrong, rest) = (src \ "answer").map(convertOption).span(!_.isCorrectOption) // assert that there is only one correct option - val checkedOptions = (wrong :+ rest.head) ++ rest.tail.map( - o => { o.setCorrectOption(false); o }) + val checkedOptions = (wrong :+ rest.head) ++ rest.tail.map(o => + o.setCorrectOption(false) + o + ) question.setOptions(checkedOptions.asJava) question.save() question.getOptions.forEach(_.save()) question - } - private def convertWeightedMultiChoice(src: Node, question: Question): Question = { + private def convertWeightedMultiChoice(src: Node, question: Question): Question = val maxScore = (src \ "defaultgrade").text.toDouble val options = (src \ "answer").map(node => convertWeightedOption(node, maxScore)) question.setOptions(options.asJava) question.save() question.getOptions.forEach(_.save()) question - } private def convertMultiChoice(src: Node, user: User): Question = - src \ "single" match { + src \ "single" match case s if s.nonEmpty && s.text == "true" => val question = convertCommon(src, user, mode = "multichoice") convertNonWeightedMultiChoice(src, question) case _ => val question = convertCommon(src, user, mode = "weighted-multichoice") convertWeightedMultiChoice(src, question) - } private def convertQuestion(src: Node, user: User): Question = - src.attribute("type").get.text match { + src.attribute("type").get.text match case "essay" => convertEssay(src, user) case "multichoice" => convertMultiChoice(src, user) case _ => logger.warn("unknown question type") throw new NoSuchElementException - } override def convert(data: String, user: User): Seq[Question] = (XML.loadString(data) \ "question").map(convertQuestion(_, user)) - -} diff --git a/app/validators/JsonSchemaValidator.java b/app/validators/JsonSchemaValidator.java index 87dd476c20..1d83c7fdf4 100644 --- a/app/validators/JsonSchemaValidator.java +++ b/app/validators/JsonSchemaValidator.java @@ -20,7 +20,6 @@ import com.networknt.schema.JsonSchemaFactory; import com.networknt.schema.SpecVersion; import com.networknt.schema.ValidationMessage; -import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -28,8 +27,9 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import javax.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import play.Environment; -import play.Logger; import play.mvc.Action; import play.mvc.Http; import play.mvc.Result; @@ -37,7 +37,7 @@ class JsonSchemaValidator extends Action { - private static final Logger.ALogger logger = Logger.of(JsonSchemaValidator.class); + private final Logger logger = LoggerFactory.getLogger(JsonSchemaValidator.class); private final Environment env; @@ -53,7 +53,7 @@ private JsonSchema getSchema() throws IOException { configuration.schema() ); JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4); - InputStream is = new FileInputStream(new File(fileName)); + InputStream is = new FileInputStream(fileName); JsonSchema schema = factory.getSchema(is); is.close(); return schema; diff --git a/build.sbt b/build.sbt index ba3e3a7629..4050cbdcad 100644 --- a/build.sbt +++ b/build.sbt @@ -1,15 +1,10 @@ -import play.sbt.PlayRunHook - -import scala.sys.process.Process -import scala.util.Properties - name := "exam" -version := "6.2.3" +version := "6.3.0" -licenses += "EUPL 1.1" -> url("http://joinup.ec.europa.eu/software/page/eupl/licence-eupl") +licenses += "EUPL 1.1" -> url("https://joinup.ec.europa.eu/software/page/eupl/licence-eupl") -scalaVersion := "2.13.8" +scalaVersion := "3.3.1" scalacOptions ++= Seq("-deprecation", "-feature") @@ -17,143 +12,45 @@ lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean) libraryDependencies ++= Seq(javaJdbc, ws, evolutions, filters, guice) -// JAXB (missing in JDK 11 and above) -libraryDependencies += "com.sun.xml.bind" % "jaxb-core" % "3.0.2" -libraryDependencies += "com.sun.xml.bind" % "jaxb-impl" % "3.0.2" -libraryDependencies += "javax.xml.bind" % "jaxb-api" % "2.3.1" -libraryDependencies += "javax.activation" % "activation" % "1.1.1" - -libraryDependencies += "be.objectify" %% "deadbolt-java" % "2.8.1" -libraryDependencies += "com.networknt" % "json-schema-validator" % "1.0.45" -libraryDependencies += "com.google.code.gson" % "gson" % "2.9.0" -libraryDependencies += "com.opencsv" % "opencsv" % "5.6" +libraryDependencies += "be.objectify" %% "deadbolt-java" % "3.0.0" +libraryDependencies += "com.networknt" % "json-schema-validator" % "1.0.82" +libraryDependencies += "com.google.code.gson" % "gson" % "2.10.1" +libraryDependencies += "com.opencsv" % "opencsv" % "5.7.1" libraryDependencies += "io.vavr" % "vavr" % "0.10.4" -libraryDependencies += "net.sf.biweekly" % "biweekly" % "0.6.6" +libraryDependencies += "net.sf.biweekly" % "biweekly" % "0.6.7" libraryDependencies += "org.apache.commons" % "commons-compress" % "1.21" libraryDependencies += "org.apache.commons" % "commons-email" % "1.5" -libraryDependencies += "org.apache.poi" % "poi" % "5.2.0" -libraryDependencies += "org.apache.poi" % "poi-ooxml" % "5.2.0" +libraryDependencies += "org.apache.poi" % "poi" % "5.2.2" +libraryDependencies += "org.apache.poi" % "poi-ooxml" % "5.2.2" libraryDependencies += "org.cryptonode.jncryptor" % "jncryptor" % "1.2.0" -libraryDependencies += "org.jsoup" % "jsoup" % "1.14.3" -libraryDependencies += "org.postgresql" % "postgresql" % "42.3.3" -libraryDependencies += "com.icegreen" % "greenmail" % "1.6.7" % "test" -libraryDependencies += "com.icegreen" % "greenmail-junit4" % "1.6.7" % "test" -libraryDependencies += "com.jayway.jsonpath" % "json-path" % "2.7.0" % "test" -libraryDependencies += "net.jodah" % "concurrentunit" % "0.4.6" % "test" -libraryDependencies += "org.eclipse.jetty" % "jetty-server" % "11.0.8" % "test" -libraryDependencies += "org.eclipse.jetty" % "jetty-servlet" % "11.0.8" % "test" -libraryDependencies += "org.easytesting" % "fest-assert" % "1.4" % "test" -libraryDependencies += "org.yaml" % "snakeyaml" % "1.30" % "test" - -dependencyOverrides += "org.slf4j" % "slf4j-api" % "1.7.36" - -javacOptions ++= Seq("-Xlint:unchecked", "-Xlint:deprecation") +libraryDependencies += "joda-time" % "joda-time" % "2.12.5" +libraryDependencies += "org.jsoup" % "jsoup" % "1.15.4" +libraryDependencies += "org.postgresql" % "postgresql" % "42.5.4" +libraryDependencies += "com.icegreen" % "greenmail" % "2.1.0-alpha-3" % "test" +libraryDependencies += "com.icegreen" % "greenmail-junit4" % "2.0.0" % "test" +libraryDependencies += "com.jayway.jsonpath" % "json-path" % "2.7.0" % "test" +libraryDependencies += "net.jodah" % "concurrentunit" % "0.4.6" % "test" +libraryDependencies += "org.eclipse.jetty" % "jetty-server" % "11.0.14" % "test" +libraryDependencies += "org.eclipse.jetty" % "jetty-servlet" % "11.0.14" % "test" +libraryDependencies += "org.easytesting" % "fest-assert" % "1.4" % "test" +libraryDependencies += "org.yaml" % "snakeyaml" % "2.0" % "test" + +javacOptions ++= Seq("-Xlint:unchecked", "-Xlint:deprecation", "-proc:full") routesImport += "util.scala.Binders._" routesGenerator := InjectedRoutesGenerator -testOptions in Test += Tests.Argument(TestFrameworks.JUnit, "-a", "-v") - -javaOptions in Test += "-Dconfig.resource=integrationtest.conf" - -sources in (Compile, doc) := Seq.empty -publishArtifact in (Compile, packageDoc) := false - -lazy val frontendDirectory = baseDirectory { - _ / "ui" -} - -lazy val protractorDirectory = baseDirectory { - _ / "ui/protractor" -} - -/** - * Webpack dev server task - */ -def withoutWebpackServer = Properties.propOrEmpty("withoutWebpackServer") - -def webpackTask = Def.taskDyn[PlayRunHook] { - if (withoutWebpackServer.equals("true")) - Def.task { - NoOp() - } else { - val webpackBuild = taskKey[Unit]("Webpack build task.") - - webpackBuild := { - Process("npm start", frontendDirectory.value).run - } - - (packageBin in Universal) := ((packageBin in Universal) dependsOn webpackBuild).value - - Def.task { - frontendDirectory.map(WebpackServer(_)).value - } - } -} - -PlayKeys.playRunHooks += webpackTask.value - -/** - * Karma test task. - */ -def skipUiTests = Properties.propOrEmpty("skipUiTests") - -def protractorConf = Properties.propOrEmpty("config.file") - -lazy val npmInstall = taskKey[Option[Process]]("Npm install task") -npmInstall := { - Some(Process("npm install", frontendDirectory.value).run()) -} - -lazy val protractorInstall = taskKey[Option[Process]]("Protractor install task") -protractorInstall := { - Some(Process("npm install", protractorDirectory.value).run()) -} - -lazy val karmaTest = taskKey[Option[Process]]("Karma test task") -karmaTest := { - Some( - Process("node_modules/karma/bin/karma start ./test/karma.conf.ci.js", frontendDirectory.value) - .run()) -} - -lazy val webDriverUpdate = taskKey[Option[Process]]("Web driver update task") -webDriverUpdate := { - Some( - Process("node_modules/protractor/bin/webdriver-manager update", protractorDirectory.value) - .run()) -} - -/*test in Test := { - if (karmaTest.value.get.exitValue() != 0) - sys.error("Karma tests failed!") - (test in Test).value -}*/ - -def uiTestTask = Def.taskDyn[Seq[PlayRunHook]] { - if (!skipUiTests.equals("true") && npmInstall.value.get - .exitValue() == 0 && protractorInstall.value.get.exitValue() == 0) { - def bdval = baseDirectory.value +Test / testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v") - def fdval = frontendDirectory.value +Test / javaOptions += "-Dconfig.resource=integrationtest.conf" - Def.task { - Seq( - if (protractorConf - .equals("conf/protractor.conf") && webDriverUpdate.value.get.exitValue() == 0) - Protractor(bdval, - Properties.propOrElse("protractor.config", "conf.js"), - Properties.propOrElse("protractor.args", " ")) - else { - Karma(fdval) - }) - } - } else { - Def.task { - Seq(NoOp()) - } - } -} +Compile / doc / sources := Seq.empty +Compile / packageDoc / publishArtifact := false -// PlayKeys.playRunHooks ++= uiTestTask.value +inThisBuild( + List( + scalaVersion := scalaVersion.value, + semanticdbEnabled := true + ) +) diff --git a/conf/application.conf b/conf/application.conf index 14841efafa..4b63582d3a 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -23,12 +23,9 @@ play.mailer.password = "password" # You can expose this datasource via JNDI if needed (Useful for JPA) # db.default.jndiName=DefaultDS db.default.driver = org.postgresql.Driver -db.default.url = "jdbc:postgresql://localhost/sitnet" -db.default.username = sitnet -db.default.password = sitnet -# Log SQL statements yes/no -db.default.logStatements = false - +db.default.url = "jdbc:postgresql://localhost/exam" +db.default.username = exam +db.default.password = exam # Number of database connections # See https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing fixedConnectionPool = 30 @@ -75,7 +72,7 @@ play.ws.timeout.connection = "10s" # database. Different institutions use roles differently, that's why we need to map externally provided roles to EXAM # roles. In the following configuration you can specify which external roles correspond to EXAM roles. In case multiple # external roles are to be mapped to a single EXAM role, the names must be comma separated. -sitnet.roles = { +exam.roles = { student = [ "student" ] @@ -88,27 +85,27 @@ sitnet.roles = { } # Login type. At the moment only HAKA is supported in production environments. -sitnet.login = "HAKA" +exam.login = "HAKA" # Hostname -sitnet.application.hostname = "http://uni.org" +exam.application.hostname = "http://uni.org" # Attachment directory. If a relative path is provided, it shall be in relation to application root path. # (/target/universal/stage in case of production environment) -sitnet.attachments.path = "/var/lib/exam/attachments" +exam.attachments.path = "/var/lib/exam/attachments" # Link to base education system URL hosted by the educational organization. Used in some of the emails targeted for # students. -sitnet.baseSystemURL = "http://base.uni.org" +exam.baseSystemURL = "http://base.uni.org" # External course interface in use: true=on, false=off -sitnet.integration.courseUnitInfo.active = true +exam.integration.courseUnitInfo.active = true # URL configuration for the course interface(s). Each URL should have the course code either as path parameter or query # parameter. Use ${course_code} for marking that part of the path. # You can specify URLs on a per-organisation basis in order to use different URLs for users that are from different # organisations. In that case the key should match with the code column of organisation relation in the database. # "default" is used if no other match is found. You can remove the "default" key if you don't want a default URL at all. -sitnet.integration.courseUnitInfo.url = { +exam.integration.courseUnitInfo.url = { default = "http://base.uni.org?courseCode=${course_code}" orgA = "http://a.uni.org?courseCode=${course_code}" orgB = "http://b.uni.org?courseCode=${course_code}" @@ -116,12 +113,12 @@ sitnet.integration.courseUnitInfo.url = { # Period during which it is allowed to import a course before its starting date. # For example if course has a starting date of June 1st and period is set to 3 months, the course can be imported # starting March 1st. Value is to be provided in ISO 8601 duration format. Default is zero days. -sitnet.integration.courseUnitInfo.window = "P0D" +exam.integration.courseUnitInfo.window = "P0D" # Enable / disable checking of permission to enroll for exams -sitnet.integration.enrolmentPermissionCheck.active = false +exam.integration.enrolmentPermissionCheck.active = false # Which user data to use as unique identifier. Permitted values are userIdentifier and eppn. -sitnet.integration.enrolmentPermissionCheck.id = "userIdentifier" +exam.integration.enrolmentPermissionCheck.id = "userIdentifier" # URL for the API implementing this check. The URL should have the employee number and language (optional) either as # path parameters or query parameters. # Use ${employee_number} and ${employee_lang} for marking these parts of the path, respectively. @@ -131,11 +128,11 @@ sitnet.integration.enrolmentPermissionCheck.id = "userIdentifier" # Response should provide EXAM with the identifiers for the courses that the person is allowed to enrol for. # Any informational messages addressed to end user should be provided in the language defined by the provided # language code. -sitnet.integration.enrolmentPermissionCheck.url = "https://uni.org/students/${employee_number}/enrolments?langcode=${employee_lang}" +exam.integration.enrolmentPermissionCheck.url = "https://uni.org/students/${employee_number}/enrolments?langcode=${employee_lang}" # API key configuration for the above external interfaces (course import and enrolment permission). # Optional. Will be passed as an HTTP header -sitnet.integration.apiKey = { +exam.integration.apiKey = { enabled = false, name = "API_KEY", value = "somevalue" @@ -144,83 +141,76 @@ sitnet.integration.apiKey = { # Interoperability (IOP) services configuration # Hostname of the IOP server provided to you by development team -sitnet.integration.iop.host = "http://xm.org" +exam.integration.iop.host = "http://xm.org" # Remote reference to your organisation provided to you by development tean -sitnet.integration.iop.organisationRef = "58a934c0e74c004753f50a9795f45327" +exam.integration.iop.organisationRef = "58a934c0e74c004753f50a9795f45327" # Visiting examination support. true=service in use, false=service not in use -sitnet.integration.iop.visit.active = false +exam.integration.iop.visit.active = false # Collaborative examination support. true=service in use, false=service not in use -sitnet.integration.iop.collaboration.active = false +exam.integration.iop.collaboration.active = false # Application timezone, used for: # - formatting timestamps in emails to users # - setting default timezone for exam rooms, this affects how and when they are eligible for reservations # - deciding the moment when user should be having an exam, system needs to take possible DST into consideration # For allowed values see: http://joda-time.sourceforge.net/timezones.html -sitnet.application.timezone = "Europe/Helsinki" +exam.application.timezone = "Europe/Helsinki" -# Exam time maximum date ahead. -# Value is to be provided in ISO 8601 duration format, default is six months -sitnet.exam.maxDate = "P6M" # Exam durations available for choosing, in minutes. The order is the same as the one end user sees on UI. # First duration is used as default. -sitnet.exam.durations = "45,90,110,180" -# Exam custom duration field min max values. Used also for verification. Empty values will use default (1 - 300) -sitnet.exam.maxDuration = 300 -sitnet.exam.minDuration = 1 +exam.exam.durations = "45,90,110,180" +# Exam custom duration field min/max values. +exam.exam.maxDuration = 300 +exam.exam.minDuration = 1 # Enable / disable possibility of users to override course grade scale for individual exams associated with the course. -sitnet.course.gradescale.overridable = true +exam.course.gradescale.overridable = true # Mail address for the system, appears in From-header of emails sent by the app. -sitnet.email.system.account = "no-reply@exam.org" +exam.email.system.account = "no-reply@exam.org" # Maximum allowed attachment file size in bytes -sitnet.attachment.maxsize = 50000000 +exam.attachment.maxsize = 50000000 # Period after which processed exams (aborted, registered or archived) are marked as deleted and thus hidden from users. # Value is to be provided in ISO 8601 duration format, default is six months -sitnet.exam.expiration.period = "P6M" +exam.exam.expiration.period = "P6M" # Enable / disable anonymous review process globally. -sitnet.exam.anonymousReview = false +exam.exam.anonymousReview = false # Enable / disable support for multiple student IDs. By default exam parses only the last ID it gets from authentication # provider. Enabling this support allows for reading in all the IDs provided should there be multiple ones. -sitnet.user.studentIds.multiple.enabled = false +exam.user.studentIds.multiple.enabled = false # Organisations associated with student IDs. A comma separated list of organisations. IDs will be presented on the UI # using this order -sitnet.user.studentIds.multiple.organisations = "org1.org,org2.org,org3.org" +exam.user.studentIds.multiple.organisations = "org1.org,org2.org,org3.org" # BYOD Examination # Enable / disable support for supervised SEB examination -sitnet.byod.seb.active = false +exam.byod.seb.active = false # Enable / disable support for unsupervised home examination -sitnet.byod.home.active = false +exam.byod.home.active = false +# Automatically grant permission to create BYOD examinations for new users with teacher role +exam.byod.permission.allowed = true # Maximum number of concurrent BYOD examination participants -sitnet.byod.maxConcurrentParticipants = 100000 +exam.byod.maxConcurrentParticipants = 100000 # SEB configuration # # Encryption key for internal storage of examination event specific SEB setting passwords. Please replace with # something stronger. -sitnet.exam.seb.settingsPwd.encryption.key = "changeme" +exam.exam.seb.settingsPwd.encryption.key = "changeme" # Link for quitting SEB after having returned the exam. Displayed for students on the EXAM UI. -sitnet.exam.seb.quitLink = "http://quit.seb.now" -# SEB client quit password. Define one if you insist that supervisors can enter it for quitting student's SEB client -# during exam. Please bear in mind that if a student gets access to this password, then nothing technically prevents her -# from quitting SEB, leaving the examination event, restarting SEB and finishing the exam elsewhere without supervision. -# Regardless of this password there's always the above quit link (sitnet.exam.seb.quitLink) for quitting SEB in a -# controlled manner. -sitnet.exam.seb.quitPwd = "" +exam.exam.seb.quitLink = "http://quit.seb.now" # SEB configuration admin password. Used to protect generated SEB configuration files so that regular users can not view # the contents using SEB configuration tool. Even if they could, modifications would not work because exam verifies that # client's configuration is unaltered. You may also choose to use randomized admin passwords in case you wish that SEB # configurations should not be viewed by anyone. -sitnet.exam.seb.adminPwd = { randomize = false, value = "changeme" } +exam.exam.seb.adminPwd = { randomize = false, value = "changeme" } # Prefix to use with courses' internal code that needs to be hidden from users. Leave empty if your course integration # does not have any internal codes that it sends. -sitnet.course.code.prefix = "_" +exam.course.code.prefix = "_" ######################################################################################################################## @@ -247,7 +237,7 @@ play.modules.enabled += "security.DeadboltHook" play.i18n.langs = ["fi", "sv", "en"] # Max disk buffer size, need to take exam max attachment file size setting into account with this -play.http.parser.maxDiskBuffer = ${sitnet.attachment.maxsize} +play.http.parser.maxDiskBuffer = ${exam.attachment.maxsize} # Max size of request payload. Default is 100K but we increase it somewhat because collaborative exam # use cases may require the client to occasionally send large-ish payloads towards server. @@ -278,14 +268,14 @@ play.filters.csrf.cookie.secure = true play.filters.csrf.header.protectHeaders = null #play.filters.https.strictTransportSecurity="max-age=31536000; includeSubDomains" -# Akka HTTP Server +# Pekko HTTP Server # Maximum allowed HTTP headers per request. The default is 64 and that is too low for transmitting all the # HAKA-attributes via shibboleth -akka.http.parsing.max-header-count = 128 +pekko.http.parsing.max-header-count = 128 # Connection settings (experimental, thus commented out) -# akka.http.server { +# pekko.http.server { # max-connections = 8192 # backlog = 1024 # } # EXAM version -exam.release.version = "6.2.3" +exam.release.version = "6.3.0" diff --git a/conf/dev.conf b/conf/dev.conf index 9537d44696..275f449f61 100644 --- a/conf/dev.conf +++ b/conf/dev.conf @@ -3,19 +3,19 @@ include "application.conf" play.mailer.mock = true # Which login is in use, local development env, or HAKA -sitnet.login = "DEBUG" -sitnet.roles.admin = ["staff"] +exam.login = "DEBUG" +exam.roles.admin = ["staff"] -sitnet.application.hostname = "http://localhost:4200" -sitnet.attachments.path = "data/attachments" -sitnet.integration.courseUnitInfo.url = { +exam.application.hostname = "http://localhost:4200" +exam.attachments.path = "data/attachments" +exam.integration.courseUnitInfo.url = { default = "http://localhost:34110/courses?courseCode=${course_code}" } -sitnet.integration.iop.host = "http://localhost:3000" -sitnet.integration.iop.organisationRef = "define me in local.conf" -sitnet.integration.iop.visit.active = true -sitnet.integration.iop.collaboration.active = true +exam.integration.iop.host = "http://localhost:3000" +exam.integration.iop.organisationRef = "define me in local.conf" +exam.integration.iop.visit.active = true +exam.integration.iop.collaboration.active = true play.filters.csrf.cookie.secure = false play.filters.headers.contentSecurityPolicy = null @@ -23,13 +23,12 @@ play.filters.csrf.header.bypassHeaders = { X-Requested-With = "*" Csrf-Token = "nocheck" } -sitnet.exam.anonymousReview = true +exam.exam.anonymousReview = true play.evolutions.autoApply = true play.evolutions.autoApplyDowns = true play.evolutions.db.default.autocommit = false -sitnet.byod.seb.active = true -sitnet.byod.home.active = true -sitnet.exam.seb.quitPwd = "quit now" +exam.byod.seb.active = true +exam.byod.home.active = true diff --git a/conf/evolutions/default/132.sql b/conf/evolutions/default/132.sql new file mode 100644 index 0000000000..6ad3979bd3 --- /dev/null +++ b/conf/evolutions/default/132.sql @@ -0,0 +1,6 @@ +# --- !Ups +ALTER TABLE examination_event_configuration ADD encrypted_quit_password BYTEA NULL; +ALTER TABLE examination_event_configuration ADD quit_password_salt VARCHAR(36) NULL; +# --- !Downs +ALTER TABLE examination_event_configuration DROP encrypted_quit_password; +ALTER TABLE examination_event_configuration DROP quit_password_salt; diff --git a/conf/evolutions/default/133.sql b/conf/evolutions/default/133.sql new file mode 100644 index 0000000000..f214fd8c0b --- /dev/null +++ b/conf/evolutions/default/133.sql @@ -0,0 +1,5 @@ +# --- !Ups +INSERT INTO permission (id, object_version, type, description) VALUES (2, 1, 2, 'can create BYOD exams') + +# --- !Downs +DELETE FROM permission where id = 2; diff --git a/conf/evolutions/default/134.sql b/conf/evolutions/default/134.sql new file mode 100644 index 0000000000..cd3c2cd1ea --- /dev/null +++ b/conf/evolutions/default/134.sql @@ -0,0 +1,5 @@ +# --- !Ups +ALTER TABLE exam_enrolment ADD delay INT NOT NULL DEFAULT 0; + +# --- !Downs +ALTER TABLE exam_enrolment DROP delay; diff --git a/conf/integrationtest.conf b/conf/integrationtest.conf index b8231b548a..478a709a90 100644 --- a/conf/integrationtest.conf +++ b/conf/integrationtest.conf @@ -1,7 +1,6 @@ include "application.conf" -db.default.url = "jdbc:postgresql://localhost/sitnet_test" -db.default.password = sitnetsitnet +db.default.url = "jdbc:postgresql://localhost/exam_test" play.mailer.host = localhost play.mailer.port = 3025 @@ -11,23 +10,23 @@ play.mailer.tls = no play.evolutions.db.default.autoApply = false play.evolutions.db.default.enabled = false -sitnet.integration.enrolmentPermissionCheck.active = true +exam.integration.enrolmentPermissionCheck.active = true -sitnet.attachments.path = "target/attachments" +exam.attachments.path = "target/attachments" # Local embedded Jetty server -sitnet.integration.courseUnitInfo.url = { +exam.integration.courseUnitInfo.url = { default = "http://localhost:31245/courseUnitInfo?courseUnitCode=${course_code}" oulu.fi = "http://localhost:31245/courseUnitInfo/oulu?courseUnitCode=${course_code}" } -sitnet.integration.iop.organisationRef = "test-org" -sitnet.integration.enrolmentPermissionCheck.url = "http://localhost:31246/enrolments?id=${employee_number}&lang=${employee_lang}" -sitnet.integration.iop.visit.active = true -sitnet.integration.iop.host = "http://localhost:31247" +exam.integration.iop.organisationRef = "test-org" +exam.integration.enrolmentPermissionCheck.url = "http://localhost:31246/enrolments?id=${employee_number}&lang=${employee_lang}" +exam.integration.iop.visit.active = true +exam.integration.iop.host = "http://localhost:31247" play.filters.csrf.header.bypassHeaders { Csrf-Token = "nocheck" } -sitnet.exam.anonymousReview = true -sitnet.user.studentIds.multiple.enabled = true -sitnet.user.studentIds.multiple.organisations = "org1.org,org2.org" +exam.exam.anonymousReview = true +exam.user.studentIds.multiple.enabled = true +exam.user.studentIds.multiple.organisations = "org1.org,org2.org" diff --git a/conf/logback.xml b/conf/logback.xml index 17338f4b19..c918c1721a 100644 --- a/conf/logback.xml +++ b/conf/logback.xml @@ -1,36 +1,41 @@ + - - + Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. +--> + - + + + + + + - + /var/log/exam/application.log - + /var/log/exam/application-log-%d{yyyy-MM-dd}.log.gz - - 90 + + 180 - - %date [%-5level] from %logger{15} in %thread - %message%n%xException{10} + + %date{yyyy-MM-dd HH:mm:ss ZZZZ} [%-5level] %logger{15} - %message%n%xException{10} - - - %date %coloredLevel %logger{15} - %message%n%xException{10} + + + %date{yyyy-MM-dd HH:mm:ss ZZZZ} %highlight(%-5level) %logger{15} - %message%n%xException{10} - + - + 512 @@ -51,16 +56,12 @@ - - - + - - diff --git a/conf/messages.en b/conf/messages.en index 82f9768a49..3e11e54592 100644 --- a/conf/messages.en +++ b/conf/messages.en @@ -53,7 +53,7 @@ email.template.exam.aborted.subject=Personal exam has been abandoned email.template.exam.aborted.message=Student {0} has aborted the exam {1} email.template.exam.returned.subject=Personal exam has been returned email.template.exam.returned.message=Student {0} has returned the exam {1} for evaluation -email.template.noshow.subject=Student {0} did not arrive for the personal exam +email.template.noshow.subject=Student did not arrive for the personal exam email.template.noshow.message=Student {0} did not use the reserved exam {1} time, no-show ical.reservation.summary=Exam reservation ical.reservation.filename=reservation{0} diff --git a/conf/messages.sv b/conf/messages.sv index 741e29eb14..ffc45a8a3c 100644 --- a/conf/messages.sv +++ b/conf/messages.sv @@ -3,11 +3,11 @@ email.inspection.comment.subject=Ny kommentar till bedömningen är tillsatt email.enrolment.no.reservation=OBS! Du har inte ännu bokat tid för tentamen! email.enrolment.no.enrolments=Inga bokningar email.weekly.report.subject=Veckosammanfattning -email.machine.reservation.subject=Bokning av examenstid +email.machine.reservation.subject=Bokning av tentamenstid email.machine.reservation.reminder.subject=Påminnelse om tentamensbokning email.review.request.subject=Du är markerad som examinator för tentamen -email.reservation.cancellation.subject=Bokningen du annullerar -email.reservation.cancellation.subject.forced=Din bokning för tentamen "{0}" är annullerad +email.reservation.cancellation.subject=Du har avbokat din tentamenstid +email.reservation.cancellation.subject.forced=Din bokning för tentamen "{0}" har avbokats email.reservation.cancellation.info=Tilläggsinformation email.template.inspection.done={0} har bedömt tentamen email.template.inspection.comment=Meddelande till andra bedömare @@ -31,13 +31,13 @@ email.template.reservation.cancel.info=Kom ihåg att annullera din bokning om di email.template.reservation.cancel.link.text=Annullera bokningen email.template.regards=Med vänliga hälsningar email.template.admin=EXAM-administratörerna -email.template.reservation.cancel.message=Din bokning för tentamen {0} kl. {1} i {2} har annullerats +email.template.reservation.cancel.message=Din bokning för tentamen {0} kl. {1} i {2} har avbokats email.template.enrolment.first={0} st varav den första på {1} email.template.weekly.report.enrolments=Bokningar email.template.weekly.report.enrolments.info=Studerandena har bokat följande tider för dina tentamina email.template.weekly.report.inspections=Obedömda prestationer email.template.weekly.report.inspections.info=Du har {0} obedömda svar i följande tentamina -email.template.reservation.cancel.message.student=Du har annullerat din tid till följande tentamen: +email.template.reservation.cancel.message.student=Du har avbokat din tid till följande tentamen: email.template.reservation.cancel.message.student.new.time=Du kan boka en ny tid till tentamen här email.template.participant.notification.subject=Personlig tentamen {0} email.template.participant.notification.title=En personlig tentamen är skapad för dig. Du bör boka tentamenstid i systemet. @@ -53,7 +53,7 @@ email.template.exam.aborted.subject=Studerande har avbrutit sin personliga tenta email.template.exam.aborted.message=Studerande {0} har avbrutit sin personliga tentamen {1} och prestationen ska inte bedömas. email.template.exam.returned.subject=En personlig tentamen är inlämnad email.template.exam.returned.message=Studerande {0} har lämnat in sin personliga tentamen {1} för bedömning. -email.template.noshow.subject=Studerande {0} kom inte till sin personliga tentamen, no-show +email.template.noshow.subject=Studerande kom inte till sin personliga tentamen, no-show email.template.noshow.message=Studerande {0} har inte använt den tentamenstid som hen hade bokat för tentamen {1}, no-show. ical.reservation.summary=Bokningen ical.reservation.filename=bokning {0} diff --git a/conf/routes b/conf/routes index f2ad8db502..012460a7ce 100644 --- a/conf/routes +++ b/conf/routes @@ -33,7 +33,7 @@ PUT /app/exams/:eid/course/:cid controlle GET /app/exams/:id/preview controllers.ExamController.getExamPreview(id: Long, request: Request) GET /app/reviewerexams controllers.ExamController.getTeachersExams(request: Request) -GET /app/examsearch controllers.ExamController.listExams(courseIds: java.util.Optional[LongList], sectionIds: java.util.Optional[LongList], tagIds: java.util.Optional[LongList], request: Request) +GET /app/examsearch controllers.ExamController.listExams(courseIds: java.util.Optional[LongList], sectionIds: java.util.Optional[LongList], tagIds: java.util.Optional[LongList], owner: java.util.Optional[LongList], request: Request) PUT /app/exam/:eid/software/:sid controllers.ExamController.updateExamSoftware(eid: Long, sid: Long, request: Request) @@ -65,6 +65,7 @@ POST /app/exam/:eid/examinationevents controll PUT /app/exam/:eid/examinationevents/:eecid controllers.ExaminationEventController.updateExaminationEvent(eid: Long, eecid: Long, request: Request) DELETE /app/exam/:eid/examinationevents/:eecid controllers.ExaminationEventController.removeExaminationEvent(eid: Long, eecid: Long) GET /app/examinationevents controllers.ExaminationEventController.listExaminationEvents(start: java.util.Optional[String], end: java.util.Optional[String]) +GET /app/examinationevents/conflicting controllers.ExaminationEventController.listOverlappingExaminationEvents(start: String, duration: Int) ############### Question review interface ############### GET /app/exam/:id/questions controllers.QuestionReviewController.getEssays(id: Long, ids: java.util.Optional[LongList], request: Request) @@ -121,6 +122,7 @@ DELETE /app/exams/:eid/sections/:sid/questions/:qid controlle PUT /app/exams/:eid/sections/:sid/reorder controllers.ExamSectionController.reorderSectionQuestions(eid: Long, sid: Long, request: Request) PUT /app/exams/:eid/reorder controllers.ExamSectionController.reorderSections(eid: Long, request: Request) GET /app/exams/question/:id/distribution controllers.ExamSectionController.getQuestionDistribution(id: Long) +GET /app/sections controllers.ExamSectionController.listSections(filter: java.util.Optional[String], courseIds: java.util.Optional[LongList], examIds: java.util.Optional[LongList], tagIds: java.util.Optional[LongList], ownerIds: java.util.Optional[LongList], request: Request) ############### Section material interface ############### GET /app/materials controllers.ExamMaterialController.listMaterials(request: Request) @@ -143,7 +145,7 @@ PUT /app/review/examquestion/:id/score controlle PUT /app/review/examquestion/:id/score/force controllers.ReviewController.forceScoreExamQuestion(id: Long, request: Request) PUT /app/review/:eid/comment controllers.ReviewController.updateComment(eid: Long, request: Request) PUT /app/review/:eid/comment/:cid/feedbackstatus controllers.ReviewController.setCommentStatusRead(eid: Long, cid: Long, request: Request) -GET /app/noshows/:eid controllers.ReviewController.listNoShows(eid: Long, request: Request) +GET /app/noshows/:eid controllers.ReviewController.listNoShows(eid: Long, collaborative: java.util.Optional[java.lang.Boolean], request: Request) PUT /app/reviews/archive controllers.ReviewController.archiveExams(request: Request) GET /app/review/:eid controllers.ReviewController.getExamReview(eid: Long, request: Request) GET /app/review/:id/locked controllers.ReviewController.hasLockedAssessments(id: Long) @@ -151,8 +153,8 @@ GET /app/examparticipations/:eid controlle GET /app/usernoshows/:eid controllers.ReviewController.listNoShowsForExamAndUser(eid: Long, request: Request) POST /app/email/inspection/:eid controllers.ReviewController.sendInspectionMessage(eid: Long, request: Request) POST /app/review/:id/inspection controllers.ReviewController.addInspectionComment(id: Long, request: Request) -POST /app/gradeimport controllers.ReviewController.importGrades(request: Request) -GET /app/exam/:eid/attachments controllers.ReviewController.getArchivedAttachments(eid: Long, start: java.util.Optional[String], end: java.util.Optional[String]) +POST /app/gradeimport controllers.ReviewDocumentsController.importGrades +GET /app/exam/:eid/attachments controllers.ReviewDocumentsController.getArchivedAttachments(eid: Long, start: Option[String], end: Option[String]) ############### Language inspection interface ############### GET /app/inspections controllers.LanguageInspectionController.listInspections(month: java.util.Optional[String], start: java.util.Optional[java.lang.Long], end: java.util.Optional[java.lang.Long]) @@ -180,12 +182,12 @@ DELETE /app/enrolments/configs/:eecid controlle ############### Courses interface ############### GET /app/courses controllers.CourseController.getCourses(filter: Option[String], q: Option[String]) -GET /app/courses/user controllers.CourseController.listUsersCourses(examIds: Option[List[Long]], sectionIds: Option[List[Long]], tagIds: Option[List[Long]]) +GET /app/courses/user controllers.CourseController.listUsersCourses(examIds: Option[List[Long]], sectionIds: Option[List[Long]], tagIds: Option[List[Long]], ownerIds: Option[List[Long]]) GET /app/courses/:id controllers.CourseController.getCourse(id: Long) ############### Question interface ############### -GET /app/questions controllers.QuestionController.getQuestions(exam: java.util.List[java.lang.Long], course: java.util.List[java.lang.Long], tag: java.util.List[java.lang.Long], section: java.util.List[java.lang.Long], request: Request) +GET /app/questions controllers.QuestionController.getQuestions(exam: java.util.List[java.lang.Long], course: java.util.List[java.lang.Long], tag: java.util.List[java.lang.Long], section: java.util.List[java.lang.Long], owner: java.util.List[java.lang.Long], request: Request) GET /app/questions/:id controllers.QuestionController.getQuestion(id: Long, request: Request) PUT /app/questions/:id controllers.QuestionController.updateQuestion(id: Long, request: Request) @@ -195,6 +197,8 @@ DELETE /app/questions/:id controlle POST /app/questions/owner/:uid controllers.QuestionController.addOwner(uid: Long, request: Request) POST /app/questions/export controllers.QuestionController.exportQuestions(request: Request) POST /app/questions/import controllers.QuestionController.importQuestions(request: Request) +GET /app/questions/:id/preview/exam controllers.QuestionController.getExamSectionQuestionPreview(id: Long, request: Request) +GET /app/questions/:id/preview/library controllers.QuestionController.getQuestionPreview(id: Long, request: Request) ############### Reservation interface ############### @@ -237,16 +241,16 @@ GET /app/machines controlle GET /app/machines/:id controllers.ExamMachineController.getExamMachine(id: Long) GET /app/machines/:id/reservations controllers.ExamMachineController.getExamMachineReservationsFromNow(id: Long) PUT /app/machines/:id controllers.ExamMachineController.updateExamMachine(id: Long, request: Request) -POST /app/machines/:id controllers.ExamMachineController.insertExamMachine(id: Long, request: Request) +POST /app/machines/:id controllers.ExamMachineController.insertExamMachine(id: Long) DELETE /app/machines/:id controllers.ExamMachineController.removeExamMachine(id: Long) POST /app/machine/:mid/software/:sid controllers.ExamMachineController.updateMachineSoftware(mid: Long, sid: Long) PUT /app/software_machine/:mid controllers.ExamMachineController.resetMachineSoftware(mid: Long) -GET /app/softwares controllers.ExamMachineController.getSoftwares +GET /app/softwares controllers.ExamMachineController.listSoftware GET /app/softwares/:id controllers.ExamMachineController.getSoftware(id: Long) DELETE /app/softwares/:id controllers.ExamMachineController.removeSoftware(id: Long) -POST /app/softwares/:name controllers.ExamMachineController.addSoftware(name: String, request: Request) +POST /app/softwares/:name controllers.ExamMachineController.addSoftware(name: String) PUT /app/softwares/:id/:name controllers.ExamMachineController.updateSoftware(id: Long, name: String) ############## Attachment ############################ @@ -406,7 +410,8 @@ GET /app/availability/:roomId/:date controlle GET /app/languages controllers.LanguageController.getSupportedLanguages ################# Tag interface ################## -GET /app/tags controllers.TagController.listTags(filter: java.util.Optional[String], examIds: java.util.Optional[LongList], courseIds: java.util.Optional[LongList], sectionIds: java.util.Optional[LongList], request: Request) +GET /app/tags controllers.TagController.listTags(filter: java.util.Optional[String], courseIds: java.util.Optional[LongList], examIds: java.util.Optional[LongList], sectionIds: java.util.Optional[LongList], owner: java.util.Optional[LongList], request: Request) +POST /app/tags/questions controllers.TagController.addTagToQuestions(request: Request) ################# General Settings interface ################## @@ -419,7 +424,6 @@ PUT /app/settings/deadline controlle GET /app/settings/reservationWindow controllers.SettingsController.getReservationWindowSize PUT /app/settings/reservationWindow controllers.SettingsController.setReservationWindowSize(request: Request) GET /app/settings/hostname controllers.SettingsController.getHostname -GET /app/settings/maxDate controllers.SettingsController.getExamMaxDate GET /app/settings/durations controllers.SettingsController.getExamDurations GET /app/settings/maxDuration controllers.SettingsController.getExamMaxDuration GET /app/settings/minDuration controllers.SettingsController.getExamMinDuration @@ -434,6 +438,7 @@ GET /app/settings/appVersion controlle GET /app/settings/maturityInstructions controllers.SettingsController.getMaturityInstructions(lang: String, ref: java.util.Optional[String]) GET /app/settings/examinationQuitLink controllers.SettingsController.getExaminationQuitLink GET /app/settings/coursecodeprefix controllers.SettingsController.getCourseCodePrefix +GET /app/settings/byodmaxparticipants controllers.SettingsController.getByodMaxParticipants ################# Statistics interface ################## @@ -458,8 +463,8 @@ POST /app/reports/questionreport/:id controlle ################# Maintenance period interface ################## GET /app/maintenance controllers.MaintenancePeriodController.listMaintenancePeriods -POST /app/maintenance controllers.MaintenancePeriodController.createMaintenancePeriod(request: Request) -PUT /app/maintenance/:id controllers.MaintenancePeriodController.updateMaintenancePeriod(id: Long, request: Request) +POST /app/maintenance controllers.MaintenancePeriodController.createMaintenancePeriod +PUT /app/maintenance/:id controllers.MaintenancePeriodController.updateMaintenancePeriod(id: Long) DELETE /app/maintenance/:id controllers.MaintenancePeriodController.removeMaintenancePeriod(id: Long) ####################################################### diff --git a/conf/seb.template.plist b/conf/seb.template.plist index fd4b377900..0744f42760 100644 --- a/conf/seb.template.plist +++ b/conf/seb.template.plist @@ -12,10 +12,22 @@ 0 URLFilterRules + aacDnsPrePinning + additionalResources + allowApplicationLog + + allowAudioCapture + allowBrowsingBackForward + allowCustomDownUploadLocation + + allowCustomDownloadLocation + + allowDeveloperConsole + allowDictation allowDictionaryLookup @@ -24,14 +36,32 @@ allowDownUploads + allowDownloads + + allowFind + allowFlashFullscreen + allowMacOSVersionNumberCheckFull + + allowMacOSVersionNumberMajor + 10 + allowMacOSVersionNumberMinor + 13 + allowMacOSVersionNumberPatch + 0 allowPDFPlugIn + allowPDFReaderToolbar + allowPreferencesWindow + allowPrint + allowQuit + allowScreenCapture + allowScreenSharing allowSiri @@ -40,6 +70,8 @@ allowSwitchToApplications + allowUploads + allowUserAppFolderInstall allowUserSwitching @@ -52,18 +84,62 @@ allowedDisplayBuiltin + allowedDisplayBuiltinEnforce + + allowedDisplayBuiltinExceptDesktop + + allowedDisplaysIgnoreFailure + allowedDisplaysMaxNumber 1 + allowiOSBetaVersionNumber + 0 + allowiOSVersionNumberMajor + 11 + allowiOSVersionNumberMinor + 0 + allowiOSVersionNumberPatch + 0 + audioControlEnabled + + audioMute + + audioSetVolumeLevel + + audioVolumeLevel + 25 + autoQuitApplications + + backgroundOpenSEBConfig + blacklistURLFilter blockPopUpWindows + blockScreenShotsLegacy + + browserMediaAutoplay + + browserMediaAutoplayAudio + + browserMediaAutoplayVideo + + browserMediaCaptureCamera + + browserMediaCaptureMicrophone + + browserMediaCaptureScreen + browserMessagingPingTime 120000 browserMessagingSocket - + ws://localhost:8706 browserScreenKeyboard + browserShowFileSystemElementPath + + browserURLSalt + browserUserAgent browserUserAgentMac @@ -78,19 +154,39 @@ 0 browserUserAgentWinTouchModeCustom + browserUserAgentWinTouchModeIPad + Mozilla/5.0 (iPad; CPU OS 12_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Mobile/15E148 Safari/604.1 + browserUserAgentiOS + 0 + browserUserAgentiOSCustom + browserViewMode 0 + browserWindowAllowAddressBar + browserWindowAllowReload browserWindowShowURL 0 + browserWindowTitleSuffix + + browserWindowWebView + 2 chooseFileToUploadPolicy 0 + configFileCreateIdentity + + configFileEncryptUsingIdentity + configKeySalt createNewDesktop + defaultPageZoomLevel + 1 + defaultTextZoomLevel + 1 detectStoppedProcess downloadAndOpenSebConfig @@ -115,8 +211,12 @@ enableBrowserWindowToolbar + enableChromeNotifications + enableCtrlEsc + enableDrawingEditor + enableEsc enableF1 @@ -143,12 +243,18 @@ enableF9 + enableFindPrinter + enableJava enableJavaScript enableLogging + enableMacOSAAC + + enableMiddleMouse + enablePlugIns enablePrintScreen @@ -157,12 +263,22 @@ enableRightMouse + enableRightMouseMac + + enableScrollLock + enableSebBrowser enableStartMenu enableTouchExit + enableURLContentFilter + + enableURLFilter + + enableWindowsUpdate + enableZoomPage enableZoomText @@ -171,6 +287,14 @@ krxHReHdQZBPxg/1x1qp4SBOt9WY+igu1165ZLE6w2g= + examSessionClearCookiesOnEnd + + examSessionClearCookiesOnStart + + examSessionReconfigureAllow + + examSessionReconfigureConfigURL + exitKey1 2 exitKey2 @@ -209,14 +333,60 @@ insideSebEnableVmWareClientShade + jitsiMeetAudioMuted + + jitsiMeetAudioOnly + + jitsiMeetEnable + + jitsiMeetFeatureFlagChat + + jitsiMeetFeatureFlagCloseCaptions + + jitsiMeetFeatureFlagDisplayMeetingName + + jitsiMeetFeatureFlagRaiseHand + + jitsiMeetFeatureFlagRecording + + jitsiMeetFeatureFlagTileView + + jitsiMeetReceiveAudio + + jitsiMeetReceiveVideo + + jitsiMeetRoom + + jitsiMeetSendAudio + + jitsiMeetSendVideo + + jitsiMeetServerURL + + jitsiMeetSubject + + jitsiMeetToken + + jitsiMeetUserInfoAvatarURL + + jitsiMeetUserInfoDisplayName + + jitsiMeetUserInfoEMail + + jitsiMeetVideoMuted + killExplorerShell + lockOnMessageSocketClose + logDirectoryOSX logDirectoryWin logLevel - 2 + 3 + logSendingRequiresAdminPassword + mainBrowserWindowHeight 100% mainBrowserWindowPositioning @@ -224,9 +394,57 @@ mainBrowserWindowWidth 100% minMacOSVersion - 0 + 6 + mobileAllowInlineMediaPlayback + + mobileAllowPictureInPictureMediaPlayback + + mobileAllowQRCodeConfig + + mobileAllowSingleAppMode + + mobileCompactAllowInlineMediaPlayback + + mobileEnableASAM + + mobileEnableGuidedAccessLinkTransform + + mobilePreventAutoLock + + mobileShowSettings + + mobileSleepModeLockScreen + + mobileStatusBarAppearance + 1 + mobileStatusBarAppearanceExtended + 1 + mobileSupportedFormFactorsCompact + + mobileSupportedFormFactorsNonTelephonyCompact + + mobileSupportedFormFactorsRegular + + mobileSupportedScreenOrientationsCompactLandscapeLeft + + mobileSupportedScreenOrientationsCompactLandscapeRight + + mobileSupportedScreenOrientationsCompactPortrait + + mobileSupportedScreenOrientationsCompactPortraitUpsideDown + + mobileSupportedScreenOrientationsRegularLandscapeLeft + + mobileSupportedScreenOrientationsRegularLandscapeRight + + mobileSupportedScreenOrientationsRegularPortrait + + mobileSupportedScreenOrientationsRegularPortraitUpsideDown + monitorProcesses + newBrowserWindowAllowAddressBar + newBrowserWindowAllowReload newBrowserWindowByLinkBlockForeign @@ -247,16 +465,34 @@ newBrowserWindowShowReloadWarning + newBrowserWindowShowURL + 0 openDownloads originatorVersion - SEB_OSX_2.1.3_29E7 + SEB_iOS_3.2.5_1456D oskBehavior 2 permittedProcesses pinEmbeddedCertificates + proctoringAIEnable + + proctoringDetectFaceAngleDisplay + + proctoringDetectFaceCount + + proctoringDetectFaceCountDisplay + + proctoringDetectFacePitch + + proctoringDetectFaceYaw + + proctoringDetectTalking + + proctoringDetectTalkingDisplay + prohibitedProcesses @@ -266,79 +502,79 @@ proxies - org_safeexambrowser_SEB_AutoConfigurationEnabled + AutoConfigurationEnabled - org_safeexambrowser_SEB_AutoConfigurationJavaScript + AutoConfigurationJavaScript - org_safeexambrowser_SEB_AutoConfigurationURL + AutoConfigurationURL - org_safeexambrowser_SEB_AutoDiscoveryEnabled + AutoDiscoveryEnabled - org_safeexambrowser_SEB_ExceptionsList + ExceptionsList - org_safeexambrowser_SEB_ExcludeSimpleHostnames + ExcludeSimpleHostnames - org_safeexambrowser_SEB_FTPEnable + FTPEnable - org_safeexambrowser_SEB_FTPPassive + FTPPassive - org_safeexambrowser_SEB_FTPPassword + FTPPassword - org_safeexambrowser_SEB_FTPPort + FTPPort 21 - org_safeexambrowser_SEB_FTPProxy + FTPProxy - org_safeexambrowser_SEB_FTPRequiresPassword + FTPRequiresPassword - org_safeexambrowser_SEB_FTPUsername + FTPUsername - org_safeexambrowser_SEB_HTTPEnable + HTTPEnable - org_safeexambrowser_SEB_HTTPPassword + HTTPPassword - org_safeexambrowser_SEB_HTTPPort + HTTPPort 80 - org_safeexambrowser_SEB_HTTPProxy + HTTPProxy - org_safeexambrowser_SEB_HTTPRequiresPassword + HTTPRequiresPassword - org_safeexambrowser_SEB_HTTPSEnable + HTTPSEnable - org_safeexambrowser_SEB_HTTPSPassword + HTTPSPassword - org_safeexambrowser_SEB_HTTPSPort + HTTPSPort 443 - org_safeexambrowser_SEB_HTTPSProxy + HTTPSProxy - org_safeexambrowser_SEB_HTTPSRequiresPassword + HTTPSRequiresPassword - org_safeexambrowser_SEB_HTTPSUsername + HTTPSUsername - org_safeexambrowser_SEB_HTTPUsername + HTTPUsername - org_safeexambrowser_SEB_RTSPEnable + RTSPEnable - org_safeexambrowser_SEB_RTSPPassword + RTSPPassword - org_safeexambrowser_SEB_RTSPPort + RTSPPort 554 - org_safeexambrowser_SEB_RTSPProxy + RTSPProxy - org_safeexambrowser_SEB_RTSPRequiresPassword + RTSPRequiresPassword - org_safeexambrowser_SEB_RTSPUsername + RTSPUsername - org_safeexambrowser_SEB_SOCKSEnable + SOCKSEnable - org_safeexambrowser_SEB_SOCKSPassword + SOCKSPassword - org_safeexambrowser_SEB_SOCKSPort + SOCKSPort 1080 - org_safeexambrowser_SEB_SOCKSProxy + SOCKSProxy - org_safeexambrowser_SEB_SOCKSRequiresPassword + SOCKSRequiresPassword - org_safeexambrowser_SEB_SOCKSUsername + SOCKSUsername proxySettingsPolicy @@ -347,6 +583,14 @@ *** quitLink *** quitURLConfirm + quitURLRestart + + raiseHandButtonAlwaysPromptMessage + + raiseHandButtonShow + + remoteProctoringViewShow + 0 removeBrowserProfile removeLocalStorage @@ -359,43 +603,140 @@ restartExamUseStartURL + screenSharingMacEnforceBlocked + sebConfigPurpose 0 sebMode 0 + sebServerConfiguration + + apiDiscovery + + clientName + + clientSecret + + institution + + pingInterval + 1000 + sebServerFallback + sebServerFallbackAttemptInterval + 2000 + sebServerFallbackAttempts + 5 + sebServerFallbackPasswordHash + + sebServerFallbackTimeout + 30000 sebServerURL + sebServiceIgnore + sebServicePolicy 2 sendBrowserExamKey + setVmwareConfiguration + + showApplicationLogButton + + showBackToStartButton + showInputLanguage showMenuBar + showNavigationButtons + + showProctoringViewButton + + showQuitButton + showReloadButton showReloadWarning + showScanQRCodeButton + + showScrollLockButton + + showSideMenu + showTaskBar showTime + startResource + startURL *** startURL *** + startURLAllowDeepLink + + startURLAppendQueryParameter + + tabFocusesLinks + taskBarHeight 40 + terminateProcesses + touchOptimized urlFilterRegex urlFilterTrustedContent + useAsymmetricOnlyEncryption + + useTemporaryDownUploadDirectory + whitelistURLFilter + zoomAPIKey + + zoomAudioMuted + + zoomEnable + + zoomFeatureFlagChat + + zoomFeatureFlagCloseCaptions + + zoomFeatureFlagRaiseHand + + zoomFeatureFlagTileView + + zoomMeetingKey + zoomMode 0 + zoomReceiveAudio + + zoomReceiveVideo + + zoomRoom + + zoomSDKToken + + zoomSendAudio + + zoomSendVideo + + zoomServerURL + + zoomSubject + + zoomToken + + zoomUserInfoDisplayName + + zoomUserName + + zoomVideoMuted + diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000000..921018143b --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,14 @@ +pre-commit: + commands: + prettier: + tags: frontend style + glob: "**/*.{ts,html}" + run: npx prettier --write {staged_files} + prettier-java: + tags: backend style + glob: "**/*.java" + run: npx prettier --write --plugin=prettier-plugin-java --print-width=120 --tab-width=4 {staged_files} + eslint: + tags: frontend rules + glob: "**/*.ts" + run: npx eslint --fix {staged_files} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..0178983fb6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14826 @@ +{ + "name": "exam", + "version": "6.3.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "exam", + "version": "6.3.0", + "license": "EUPL-1.1", + "dependencies": { + "@angular/animations": "^17.0.9", + "@angular/cdk": "^17.0.0", + "@angular/common": "^17.0.9", + "@angular/compiler": "^17.0.9", + "@angular/core": "^17.0.9", + "@angular/forms": "^17.0.9", + "@angular/localize": "^17.0.9", + "@angular/platform-browser": "^17.0.9", + "@angular/platform-browser-dynamic": "^17.0.9", + "@angular/router": "^17.0.9", + "@fullcalendar/angular": "^6.0.3", + "@fullcalendar/luxon2": "^6.0.3", + "@fullcalendar/timegrid": "^6.0.3", + "@ng-bootstrap/ng-bootstrap": "^16.0.0", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@popperjs/core": "^2.10.2", + "bootstrap": "^5.3.2", + "bootstrap-icons": "^1.3.0", + "chart.js": "^3.8.0", + "chartjs-plugin-datalabels": "^2.0.0", + "date-fns": "^2.25.0", + "file-saver-es": "^2.0.5", + "luxon": "^2.0.0", + "ngx-toastr": "^16.0.2", + "ngx-webstorage-service": "^5.0.0", + "ramda": "^0.28.0", + "rxjs": "^7.4.0", + "zone.js": "^0.14.3" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.0.10", + "@angular-eslint/builder": "^17.2.0", + "@angular-eslint/eslint-plugin": "^17.2.0", + "@angular-eslint/eslint-plugin-template": "^17.2.0", + "@angular-eslint/schematics": "^17.2.0", + "@angular-eslint/template-parser": "^17.2.0", + "@angular/cli": "^17.0.10", + "@angular/compiler-cli": "^17.0.9", + "@types/ckeditor": "^4.9.10", + "@types/file-saver-es": "^2.0.1", + "@types/jasmine": "^3.10.0", + "@types/luxon": "^3.1.0", + "@types/mathjax": "^0.0.37", + "@types/ramda": "^0.28.14", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "@typescript-eslint/parser": "^6.10.0", + "eslint": "^8.53.0", + "eslint-plugin-deprecation": "^2.0.0", + "eslint-plugin-no-relative-import-paths": "^1.5.4", + "karma": "^6.3.0", + "lefthook": "^1.6.1", + "prettier": "^3.0.0", + "prettier-plugin-java": "^2.5.0", + "prettier-plugin-organize-imports": "^3.2.4", + "typescript": "~5.3.0", + "webpack-bundle-analyzer": "^4.5.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1701.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1701.2.tgz", + "integrity": "sha512-g3gn5Ht6r9bCeFeAYF+HboZB8IvgvqqdeOnaWNaXJLI0ymEkpbqRdqrHGuVKHJV7JOMNXC7GPJEctBC6SXxOxA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "17.1.2", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.1.2.tgz", + "integrity": "sha512-QIDTP+TjiCKCYRZYb8to4ymvIV1Djcfd5c17VdgMGhRqIQAAK1V4f4A1njdhGYOrgsLajZQAnKvFfk2ZMeI37A==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.2.1", + "@angular-devkit/architect": "0.1701.2", + "@angular-devkit/build-webpack": "0.1701.2", + "@angular-devkit/core": "17.1.2", + "@babel/core": "7.23.7", + "@babel/generator": "7.23.6", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.22.6", + "@babel/plugin-transform-async-generator-functions": "7.23.7", + "@babel/plugin-transform-async-to-generator": "7.23.3", + "@babel/plugin-transform-runtime": "7.23.7", + "@babel/preset-env": "7.23.7", + "@babel/runtime": "7.23.7", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "17.1.2", + "@vitejs/plugin-basic-ssl": "1.0.2", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.16", + "babel-loader": "9.1.3", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "^4.21.5", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.20", + "css-loader": "6.8.1", + "esbuild-wasm": "0.19.11", + "fast-glob": "3.3.2", + "http-proxy-middleware": "2.0.6", + "https-proxy-agent": "7.0.2", + "inquirer": "9.2.12", + "jsonc-parser": "3.2.0", + "karma-source-map-support": "1.4.0", + "less": "4.2.0", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.30.5", + "mini-css-extract-plugin": "2.7.6", + "mrmime": "2.0.0", + "open": "8.4.2", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "3.0.1", + "piscina": "4.2.1", + "postcss": "8.4.33", + "postcss-loader": "7.3.4", + "resolve-url-loader": "5.0.0", + "rxjs": "7.8.1", + "sass": "1.69.7", + "sass-loader": "13.3.3", + "semver": "7.5.4", + "source-map-loader": "5.0.0", + "source-map-support": "0.5.21", + "terser": "5.26.0", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.6.2", + "undici": "6.2.1", + "vite": "5.0.12", + "watchpack": "2.4.0", + "webpack": "5.89.0", + "webpack-dev-middleware": "6.1.1", + "webpack-dev-server": "4.15.1", + "webpack-merge": "5.10.0", + "webpack-subresource-integrity": "5.1.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "esbuild": "0.19.11" + }, + "peerDependencies": { + "@angular/compiler-cli": "^17.0.0", + "@angular/localize": "^17.0.0", + "@angular/platform-server": "^17.0.0", + "@angular/service-worker": "^17.0.0", + "@web/test-runner": "^0.18.0", + "browser-sync": "^3.0.2", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "karma": "^6.3.0", + "ng-packagr": "^17.0.0", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=5.2 <5.4" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "@web/test-runner": { + "optional": true + }, + "browser-sync": { + "optional": true + }, + "jest": { + "optional": true + }, + "jest-environment-jsdom": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1701.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1701.2.tgz", + "integrity": "sha512-LqfSO5iTbiYByDadUET/8uIun8vSHMEdtoxiil/kdZ5T0NG0p7K8QqUMnWgg6suwO6kFfYJkMiS8Dq3Y/ONUNQ==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1701.2", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^5.30.0", + "webpack-dev-server": "^4.0.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.1.2.tgz", + "integrity": "sha512-ku+/W/HMCBacSWFppenr9y6Lx8mDuTuQvn1IkTyBLiJOpWnzgVbx9kHDeaDchGa1PwLlJUBBrv27t3qgJOIDPw==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "picomatch": "3.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.1.2.tgz", + "integrity": "sha512-8S9RuM8olFN/gwN+mjbuF1CwHX61f0i59EGXz9tXLnKRUTjsRR+8vVMTAmX0dvVAT5fJTG/T69X+HX7FeumdqA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "17.1.2", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.5", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-eslint/builder": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-17.2.1.tgz", + "integrity": "sha512-O30eaR0wCPiP+zKWvXj2JM8hVq30Wok2rp7zJMFm3PurjF9nWIIyexXkE5fa538DYZYxu8N3gQRqhpv5jvTXCg==", + "dev": true, + "dependencies": { + "@nx/devkit": "17.2.8", + "nx": "17.2.8" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.2.1.tgz", + "integrity": "sha512-puC0itsZv2QlrDOCcWtq1KZH+DvfrpV+mV78HHhi6+h25R5iIhr8ARKcl3EQxFjvrFq34jhG8pSupxKvFbHVfA==", + "dev": true + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-17.2.1.tgz", + "integrity": "sha512-9yA81BHpsaCUKRBtHGN3ieAy8HpIoffzPQMu34lYqZFT4yGHGhYmhQjNSQGBRbV2LD9dVv2U35rMHNmUcozXpw==", + "dev": true, + "dependencies": { + "@angular-eslint/utils": "17.2.1", + "@typescript-eslint/utils": "6.19.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-17.2.1.tgz", + "integrity": "sha512-hl1hcHtcm90wyVL1OQGTz16oA0KHon+FFb3Qg0fLXObaXxA495Ecefd9ub5Xxg4JEOPRDi29bF1Y3YKpwflgeg==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "17.2.1", + "@angular-eslint/utils": "17.2.1", + "@typescript-eslint/type-utils": "6.19.0", + "@typescript-eslint/utils": "6.19.0", + "aria-query": "5.3.0", + "axobject-query": "4.0.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/schematics": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-17.2.1.tgz", + "integrity": "sha512-7ldtIePI4ZTp/TBpeOZkzfv30HSAn//4TgtFuqvojudI8n8batV5FqQ0VNm1e0zitl75t8Zwtr0KYT4I6vh59g==", + "dev": true, + "dependencies": { + "@angular-eslint/eslint-plugin": "17.2.1", + "@angular-eslint/eslint-plugin-template": "17.2.1", + "@nx/devkit": "17.2.8", + "ignore": "5.3.0", + "nx": "17.2.8", + "strip-json-comments": "3.1.1", + "tmp": "0.2.1" + }, + "peerDependencies": { + "@angular/cli": ">= 17.0.0 < 18.0.0" + } + }, + "node_modules/@angular-eslint/template-parser": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-17.2.1.tgz", + "integrity": "sha512-WPQYFvRju0tCDXQ/pwrzC911pE07JvpeDgcN2elhzV6lxDHJEZpA5O9pnW9qgNA6J6XM9Q7dBkJ22ztAzC4WFw==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "17.2.1", + "eslint-scope": "^8.0.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/utils": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-17.2.1.tgz", + "integrity": "sha512-qQYTBXy90dWM7fhhpa5i9lTtqqhJisvRa+naCrQx9kBgR458JScLdkVIdcZ9D/rPiDCmKiVUfgcDISnjUeqTqg==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "17.2.1", + "@typescript-eslint/utils": "6.19.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular/animations": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.1.2.tgz", + "integrity": "sha512-ZsHa/zoWBOZdispjcNgXCoF9MAtc6Zyzc/QFUjtOFI9vigOI8tWP6GY1Wfeg4cyL+R3uDGYBgMrdr8l84VfuKg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/core": "17.1.2" + } + }, + "node_modules/@angular/cdk": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-17.1.2.tgz", + "integrity": "sha512-eu9D60RQv213qi7oh6ae9Z+d6+AG/aqi0y70Ag9BjwqTiatDiYvSySxswxYYKdzPp0hx0ZUTGi16LqtT6pyj6Q==", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^17.0.0 || ^18.0.0", + "@angular/core": "^17.0.0 || ^18.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/cli": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.1.2.tgz", + "integrity": "sha512-U1W6XZNrfeRkXW2fO3AU25rRttqZahVkhzcK3lAtJ8+lSrStCOF7x1gz6tmFZFte1fNHQrXqD0yIDkd8H2/cvw==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1701.2", + "@angular-devkit/core": "17.1.2", + "@angular-devkit/schematics": "17.1.2", + "@schematics/angular": "17.1.2", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "4.1.1", + "inquirer": "9.2.12", + "jsonc-parser": "3.2.0", + "npm-package-arg": "11.0.1", + "npm-pick-manifest": "9.0.0", + "open": "8.4.2", + "ora": "5.4.1", + "pacote": "17.0.5", + "resolve": "1.22.8", + "semver": "7.5.4", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, + "bin": { + "ng": "bin/ng.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/common": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-17.1.2.tgz", + "integrity": "sha512-y/wD+zuPaPgK3dB80Q63qBtuu5TuryKuUgjWrOmrguBWV9oiJRhKQrcp1gVw9vVrowmbDBKGtPMS622Q4oxOWQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/core": "17.1.2", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.1.2.tgz", + "integrity": "sha512-1vJuQRM5V01nC6qsLvBKrHVZXpzbK0YKubwVQUXCSfDNZBcDFak3SQcwU4C2t880rU3ZvFDB1UWfk7CKn5w9Kw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/core": "17.1.2" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/compiler-cli": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.1.2.tgz", + "integrity": "sha512-4P4ttCe4IF9yq7bxCDxbVW7purN7qV0nqofP5Tth1xCsgIJeGmOMMQJN5RJCZNrAPMkvMv39eV878sgcDjbpOA==", + "dependencies": { + "@babel/core": "7.23.2", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/index.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/compiler": "17.1.2", + "typescript": ">=5.2 <5.4" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/core": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.1.2.tgz", + "integrity": "sha512-0M787BZVgYSVogHCUzo/dFrT56TgfQoEsOQngHMpyERJZv6dycXZlRdHc6TzvHUa+Uu/MNjn/RclBR8063bdWA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.14.0" + } + }, + "node_modules/@angular/forms": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.1.2.tgz", + "integrity": "sha512-n1WsZAL2IVOB6ocROKR6CFOR14PIC9RGAB41SwTfPhJeBM1kjW48bXY0sw97TasxM4mWJKGCmFXu0jQwkoeSpQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.1.2", + "@angular/core": "17.1.2", + "@angular/platform-browser": "17.1.2", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/localize": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.1.2.tgz", + "integrity": "sha512-9HE1vrgcz90EgU/eZKtUZJlec5kePvTj3pNim1/FLsEjDpN8sBn1QYrPTIWDCySSXPAkMfAcZBODYdPBXWVi8A==", + "dependencies": { + "@babel/core": "7.23.2", + "@types/babel__core": "7.20.2", + "fast-glob": "3.3.1", + "yargs": "^17.2.1" + }, + "bin": { + "localize-extract": "tools/bundles/src/extract/cli.js", + "localize-migrate": "tools/bundles/src/migrate/cli.js", + "localize-translate": "tools/bundles/src/translate/cli.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/compiler": "17.1.2", + "@angular/compiler-cli": "17.1.2" + } + }, + "node_modules/@angular/localize/node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/localize/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@angular/localize/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@angular/localize/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/platform-browser": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.1.2.tgz", + "integrity": "sha512-unfpA5OLnqDmDb/oAQR2t2iROpOg02qwZayxyFg4MUZdDdnghPCfX77L2sr6oVVa7OJfKYFlmwmBXX1H3zjcXA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/animations": "17.1.2", + "@angular/common": "17.1.2", + "@angular/core": "17.1.2" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.1.2.tgz", + "integrity": "sha512-xiWVDHbA+owDhKo5SAnzZtawA1ktGthlCl3YTI+vmkJpF6axkYOqR7YL+aEQX/y/5GSK+oR+03SgAnYcpOwKlQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.1.2", + "@angular/compiler": "17.1.2", + "@angular/core": "17.1.2", + "@angular/platform-browser": "17.1.2" + } + }, + "node_modules/@angular/router": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-17.1.2.tgz", + "integrity": "sha512-8OexxiiscRdfEiB6jOKlZFyAKZtvIQvh0ugW6U7nAXPV5XsA2UL80sXkc829eH0DnJn2Wj/HS6ZNGgG81PWDHg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.1.2", + "@angular/core": "17.1.2", + "@angular/platform-browser": "17.1.2", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.23.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", + "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "dependencies": { + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", + "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz", + "integrity": "sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.7", + "babel-plugin-polyfill-corejs3": "^0.8.7", + "babel-plugin-polyfill-regenerator": "^0.5.4", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.7.tgz", + "integrity": "sha512-SY27X/GtTz/L4UryMNJ6p4fH4nsgWbz84y9FE0bQeWJP6O5BhgVCt53CotQKHCOeXJel8VyhlhujhlltKms/CA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.7", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.5", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.3", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.7", + "babel-plugin-polyfill-corejs3": "^0.8.7", + "babel-plugin-polyfill-regenerator": "^0.5.4", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz", + "integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", + "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", + "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", + "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", + "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", + "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", + "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", + "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", + "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", + "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", + "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", + "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", + "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", + "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", + "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", + "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", + "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", + "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", + "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", + "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", + "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", + "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", + "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", + "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@fullcalendar/angular": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.10.tgz", + "integrity": "sha512-y0aIC5Zexu8PaULF4u+K8LzMVu8pI7kLkEI53c7gV2/1OOGMg5Ld3tVeuArsHfAdlPdOqiWa/q2/ECZj28/Izg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "12 - 17", + "@angular/core": "12 - 17", + "@fullcalendar/core": "~6.1.10" + } + }, + "node_modules/@fullcalendar/core": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.10.tgz", + "integrity": "sha512-oTXGJSAGpCf1oY+CKp5qYjMHkJCPBkJ3SHitl63n8Q6xKeiwQ4EF6Au451euUovREwJpLmD1AyZrCnWmtB9AVg==", + "peer": true, + "dependencies": { + "preact": "~10.12.1" + } + }, + "node_modules/@fullcalendar/daygrid": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.10.tgz", + "integrity": "sha512-Z4GRm1IyHKgxXFTWGcEI0nTsvYOIkpE0aMt3/o3ER2SZkF+hfwcDFhtj0c9+WhMjXFIWYeoTnA9rUOY7Zl/nxA==", + "peerDependencies": { + "@fullcalendar/core": "~6.1.10" + } + }, + "node_modules/@fullcalendar/luxon2": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/luxon2/-/luxon2-6.1.10.tgz", + "integrity": "sha512-1a8wgzRgE4znQNoHzNyy7T3N7uzDB2wPxP2DCEMVCrgJIk5i86FDSWt78hQd6rk1emjKd7qyjUgGzKy7iBfOIw==", + "peerDependencies": { + "@fullcalendar/core": "~6.1.10", + "luxon": "^2.0.0" + } + }, + "node_modules/@fullcalendar/timegrid": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.10.tgz", + "integrity": "sha512-hFKyQXJaPbNyq1reZmvkCmM64O99krHoIcJAbDS+dntCm3FzZUcDtAcRKIbMiantHrezCG/1MEYk3m9e3aKvIQ==", + "dependencies": { + "@fullcalendar/daygrid": "~6.1.10" + }, + "peerDependencies": { + "@fullcalendar/core": "~6.1.10" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, + "node_modules/@ljharb/through": { + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", + "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/@ng-bootstrap/ng-bootstrap": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-16.0.0.tgz", + "integrity": "sha512-+FJ3e6cX9DW2t7021Ji3oz433rk3+4jLfqzU+Jyx6/vJz1dIOaML3EAY6lYuW4TLiXgMPOMvs6KzPFALGh4Lag==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.0", + "@angular/core": "^17.0.0", + "@angular/forms": "^17.0.0", + "@angular/localize": "^17.0.0", + "@popperjs/core": "^2.11.8", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@ngtools/webpack": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.1.2.tgz", + "integrity": "sha512-MdNVSIp0x8AK26L+CxMTXH4weq2sNIp4C09RSdk7y6UkfBxMA3O0jTto9tW3ehkBaaGZ4dSiWkXA8L/ydMiQmA==", + "dev": true, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^17.0.0", + "typescript": ">=5.2 <5.4", + "webpack": "^5.54.0" + } + }, + "node_modules/@ngx-translate/core": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", + "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": ">=13.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@ngx-translate/http-loader": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz", + "integrity": "sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@ngx-translate/core": ">=14.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", + "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.4.tgz", + "integrity": "sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.0.tgz", + "integrity": "sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==", + "dev": true, + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz", + "integrity": "sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==", + "dev": true, + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", + "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@nrwl/devkit": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-17.2.8.tgz", + "integrity": "sha512-l2dFy5LkWqSA45s6pee6CoqJeluH+sjRdVnAAQfjLHRNSx6mFAKblyzq5h1f4P0EUCVVVqLs+kVqmNx5zxYqvw==", + "dev": true, + "dependencies": { + "@nx/devkit": "17.2.8" + } + }, + "node_modules/@nrwl/tao": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-17.2.8.tgz", + "integrity": "sha512-Qpk5YKeJ+LppPL/wtoDyNGbJs2MsTi6qyX/RdRrEc8lc4bk6Cw3Oul1qTXCI6jT0KzTz+dZtd0zYD/G7okkzvg==", + "dev": true, + "dependencies": { + "nx": "17.2.8", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/devkit": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-17.2.8.tgz", + "integrity": "sha512-6LtiQihtZwqz4hSrtT5cCG5XMCWppG6/B8c1kNksg97JuomELlWyUyVF+sxmeERkcLYFaKPTZytP0L3dmCFXaw==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "17.2.8", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "semver": "7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "nx": ">= 16 <= 18" + } + }, + "node_modules/@nx/devkit/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/devkit/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/devkit/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.2.8.tgz", + "integrity": "sha512-dMb0uxug4hM7tusISAU1TfkDK3ixYmzc1zhHSZwpR7yKJIyKLtUpBTbryt8nyso37AS1yH+dmfh2Fj2WxfBHTg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-darwin-x64": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-17.2.8.tgz", + "integrity": "sha512-0cXzp1tGr7/6lJel102QiLA4NkaLCkQJj6VzwbwuvmuCDxPbpmbz7HC1tUteijKBtOcdXit1/MEoEU007To8Bw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.2.8.tgz", + "integrity": "sha512-YFMgx5Qpp2btCgvaniDGdu7Ctj56bfFvbbaHQWmOeBPK1krNDp2mqp8HK6ZKOfEuDJGOYAp7HDtCLvdZKvJxzA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.2.8.tgz", + "integrity": "sha512-iN2my6MrhLRkVDtdivQHugK8YmR7URo1wU9UDuHQ55z3tEcny7LV3W9NSsY9UYPK/FrxdDfevj0r2hgSSdhnzA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.2.8.tgz", + "integrity": "sha512-Iy8BjoW6mOKrSMiTGujUcNdv+xSM1DALTH6y3iLvNDkGbjGK1Re6QNnJAzqcXyDpv32Q4Fc57PmuexyysZxIGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.2.8.tgz", + "integrity": "sha512-9wkAxWzknjpzdofL1xjtU6qPFF1PHlvKCZI3hgEYJDo4mQiatGI+7Ttko+lx/ZMP6v4+Umjtgq7+qWrApeKamQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.2.8.tgz", + "integrity": "sha512-sjG1bwGsjLxToasZ3lShildFsF0eyeGu+pOQZIp9+gjFbeIkd19cTlCnHrOV9hoF364GuKSXQyUlwtFYFR4VTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.2.8.tgz", + "integrity": "sha512-QiakXZ1xBCIptmkGEouLHQbcM4klQkcr+kEaz2PlNwy/sW3gH1b/1c0Ed5J1AN9xgQxWspriAONpScYBRgxdhA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.2.8.tgz", + "integrity": "sha512-XBWUY/F/GU3vKN9CAxeI15gM4kr3GOBqnzFZzoZC4qJt2hKSSUEWsMgeZtsMgeqEClbi4ZyCCkY7YJgU32WUGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.2.8.tgz", + "integrity": "sha512-HTqDv+JThlLzbcEm/3f+LbS5/wYQWzb5YDXbP1wi7nlCTihNZOLNqGOkEmwlrR5tAdNHPRpHSmkYg4305W0CtA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.24", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.24.tgz", + "integrity": "sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==", + "dev": true + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", + "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", + "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", + "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", + "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", + "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", + "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", + "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", + "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", + "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", + "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", + "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", + "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", + "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@schematics/angular": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.1.2.tgz", + "integrity": "sha512-1GlH0POaN7hVDF1sAm90E5SvAqnKK+PbD1oKSpug9l+1AUQ3vOamyGhEAaO+IxUqvNdgqZexxd5o9MyySTT2Zw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "17.1.2", + "@angular-devkit/schematics": "17.1.2", + "jsonc-parser": "3.2.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@sigstore/bundle": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.1.tgz", + "integrity": "sha512-v3/iS+1nufZdKQ5iAlQKcCsoh0jffQyABvYIxKsZQFWc4ubuGjwZklFHpDgV6O6T7vvV78SW5NHI91HFKEcxKg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-0.2.0.tgz", + "integrity": "sha512-THobAPPZR9pDH2CAvDLpkrYedt7BlZnsyxDe+Isq4ZmGfPy5juOFZq487vCU2EgKD7aHSiTfE/i7sN7aEdzQnA==", + "dev": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.1.tgz", + "integrity": "sha512-U5sKQEj+faE1MsnLou1f4DQQHeFZay+V9s9768lw48J4pKykPj34rWyI1lsMOGJ3Mae47Ye6q3HAJvgXO21rkQ==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.0.tgz", + "integrity": "sha512-S98jo9cpJwO1mtQ+2zY7bOdcYyfVYCUaofCG6wWRzk3pxKHVAkSfshkfecto2+LKsx7Ovtqbgb2LS8zTRhxJ9Q==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1", + "tuf-js": "^2.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-0.1.0.tgz", + "integrity": "sha512-2UzMNYAa/uaz11NhvgRnIQf4gpLTJ59bhb8ESXaoSS5sxedfS+eLak8bsdMc+qpNQfITUTFoSKFx5h8umlRRiA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "dev": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.0.tgz", + "integrity": "sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ckeditor": { + "version": "4.9.10", + "resolved": "https://registry.npmjs.org/@types/ckeditor/-/ckeditor-4.9.10.tgz", + "integrity": "sha512-dcOPCXM0Cr5Z0i6eF/aW5LvECrS+cdl2Gi7lU+rEUNWby0w9Yl6mBubjrs29OVAducpuZjB4mfDayE+o4/gGdQ==", + "dev": true + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz", + "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/file-saver-es": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/file-saver-es/-/file-saver-es-2.0.3.tgz", + "integrity": "sha512-1N7YkjKDfSSlBq9TCbNelivW+CkqEGh6HWzOP2w8znKsyASufdp8ymxnmKs67hyO9r175xMUu1e2w50xfBD4Ew==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "3.10.18", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.18.tgz", + "integrity": "sha512-jOk52a1Kz+1oU5fNWwAcNe64/GsE7r/Q6ronwDox0D3ETo/cr4ICMQyeXrj7G6FPW1n8YjRoAZA2F0XBr6GicQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/luxon": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", + "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==", + "dev": true + }, + "node_modules/@types/mathjax": { + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@types/mathjax/-/mathjax-0.0.37.tgz", + "integrity": "sha512-y0WSZBtBNQwcYipTU/BhgeFu1EZNlFvUNCmkMXV9kBQZq7/o5z82dNVyH3yy2Xv5zzeNeQoHSL4Xm06+EQiH+g==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "dev": true + }, + "node_modules/@types/ramda": { + "version": "0.28.25", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.25.tgz", + "integrity": "sha512-HrQNqQAGcITpn9HAJFamDxm7iZeeXiP/95pN5OMbNniDjzCCeOHbBKNGmUy8NRi0fhYS+/cXeo91MFC+06gbow==", + "dev": true, + "dependencies": { + "ts-toolbelt": "^6.15.1" + } + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", + "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/utils": "6.19.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", + "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", + "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", + "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.19.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", + "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", + "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", + "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", + "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", + "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.19.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-basic-ssl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.2.tgz", + "integrity": "sha512-DKHKVtpI+eA5fvObVgQ3QtTGU70CcCnedalzqmGSR050AzKZMdUzgC8KmlOneHWH8dF2hJ3wkC9+8FDVAaDRCw==", + "dev": true, + "engines": { + "node": ">=14.6.0" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.15.0" + } + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@zkochan/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.5.0", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", + "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.4", + "core-js-compat": "^3.33.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", + "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/bootstrap": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", + "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/bootstrap-icons": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz", + "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", + "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/call-bind": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", + "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "set-function-length": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001584", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", + "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chart.js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", + "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" + }, + "node_modules/chartjs-plugin-datalabels": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", + "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", + "peerDependencies": { + "chart.js": ">=3.0.0" + } + }, + "node_modules/chevrotain": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-6.5.0.tgz", + "integrity": "sha512-BwqQ/AgmKJ8jcMEjaSnfMybnKMgGTrtDKowfTP3pX4jwVy0kNjRsT/AP6h+wC3+3NC+X8X15VWBnTCQlX+wQFg==", + "dev": true, + "dependencies": { + "regexp-to-ast": "0.4.0" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js-compat": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", + "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", + "dev": true, + "dependencies": { + "browserslist": "^4.22.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/critters": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", + "integrity": "sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "pretty-bytes": "^5.3.0" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/critters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/critters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/critters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "dev": true + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", + "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.657", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.657.tgz", + "integrity": "sha512-On2ymeleg6QbRuDk7wNgDdXtNqlJLM2w4Agx1D/RiTmItiL+a9oq5p7HUa2ZtkAtGBe/kil2dq/7rPfkbe0r5w==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", + "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "devOptional": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", + "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.11", + "@esbuild/android-arm": "0.19.11", + "@esbuild/android-arm64": "0.19.11", + "@esbuild/android-x64": "0.19.11", + "@esbuild/darwin-arm64": "0.19.11", + "@esbuild/darwin-x64": "0.19.11", + "@esbuild/freebsd-arm64": "0.19.11", + "@esbuild/freebsd-x64": "0.19.11", + "@esbuild/linux-arm": "0.19.11", + "@esbuild/linux-arm64": "0.19.11", + "@esbuild/linux-ia32": "0.19.11", + "@esbuild/linux-loong64": "0.19.11", + "@esbuild/linux-mips64el": "0.19.11", + "@esbuild/linux-ppc64": "0.19.11", + "@esbuild/linux-riscv64": "0.19.11", + "@esbuild/linux-s390x": "0.19.11", + "@esbuild/linux-x64": "0.19.11", + "@esbuild/netbsd-x64": "0.19.11", + "@esbuild/openbsd-x64": "0.19.11", + "@esbuild/sunos-x64": "0.19.11", + "@esbuild/win32-arm64": "0.19.11", + "@esbuild/win32-ia32": "0.19.11", + "@esbuild/win32-x64": "0.19.11" + } + }, + "node_modules/esbuild-wasm": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.19.11.tgz", + "integrity": "sha512-MIhnpc1TxERUHomteO/ZZHp+kUawGEc03D/8vMHGzffLvbFLeDe6mwxqEZwlqBNY7SLWbyp6bBQAcCen8+wpjQ==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-deprecation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-deprecation/-/eslint-plugin-deprecation-2.0.0.tgz", + "integrity": "sha512-OAm9Ohzbj11/ZFyICyR5N6LbOIvQMp7ZU2zI7Ej0jIc8kiGUERXPNMfw2QqqHD1ZHtjMub3yPZILovYEYucgoQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^6.0.0", + "tslib": "^2.3.1", + "tsutils": "^3.21.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "typescript": "^4.2.4 || ^5.0.0" + } + }, + "node_modules/eslint-plugin-no-relative-import-paths": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-relative-import-paths/-/eslint-plugin-no-relative-import-paths-1.5.4.tgz", + "integrity": "sha512-2smViH7R3682NR6dwgYr8Vm7emqNP1gEjBku6DbvUy3Ef/2Fz+mhwsFjZGSixzWzazMCj4MAgIWTsHELCCDJKA==", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.0.tgz", + "integrity": "sha512-zj3Byw6jX4TcFCJmxOzLt6iol5FAr9xQyZZSQjEzW2UiCJXLwXdRIKCYVFftnpZckaC9Ps9xlC7jB8tSeWWOaw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-saver-es": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver-es/-/file-saver-es-2.0.5.tgz", + "integrity": "sha512-Kg0lt+is9nOyi/VDms9miScNGot25jVFbjFccXuCL/shd2Q+rt70MALxHVkXllsX83JEBLiHQNjDPGd/6FIOoQ==" + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "dependencies": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "node_modules/hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "node_modules/hosted-git-info": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", + "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", + "dev": true, + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/inquirer": { + "version": "9.2.12", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", + "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", + "dev": true, + "dependencies": { + "@ljharb/through": "^2.3.11", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^5.0.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/java-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-2.2.0.tgz", + "integrity": "sha512-20/Rpuv4FnzTNgWkJBqs2M4qwBuPLMqOqNiwU5j7vKvrw4Ej+re8Aoc92KbDFb61M1u/Sd4Ygst+CpEcKXvhBQ==", + "dev": true, + "dependencies": { + "chevrotain": "6.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/karma": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", + "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/karma/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/karma/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/karma/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/karma/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/lefthook": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-1.6.1.tgz", + "integrity": "sha512-1T+tk0V6ubZgiZJGi39QlLMAcgEw+lhoDeSpT3L8Y/f8nUpJW9ntcMOmt+uvMfQ3TVjNcR1r/Lhtm7gTqgdcPg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "lefthook": "bin/index.js" + }, + "optionalDependencies": { + "lefthook-darwin-arm64": "1.6.1", + "lefthook-darwin-x64": "1.6.1", + "lefthook-freebsd-arm64": "1.6.1", + "lefthook-freebsd-x64": "1.6.1", + "lefthook-linux-arm64": "1.6.1", + "lefthook-linux-x64": "1.6.1", + "lefthook-windows-arm64": "1.6.1", + "lefthook-windows-x64": "1.6.1" + } + }, + "node_modules/lefthook-darwin-arm64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.6.1.tgz", + "integrity": "sha512-q6+sYr2Dpt6YnBGXRjMFcXZUnVB97nH+s7EP/tX8m9ewvQxLPqIiUPyAumfyJ2Siomkc5WgAinG+kT63VjUN3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/lefthook-darwin-x64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-1.6.1.tgz", + "integrity": "sha512-utm7FwtbW8SxGMALIw5/iG4loYS2FI0crDKp/YIamrZgQr6M4pS2C3rxGj5OwiHFIm3arVU+3VZywdvRLJAw0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/lefthook-freebsd-arm64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.6.1.tgz", + "integrity": "sha512-F2BoDnGznkJyn6lyhmXpu62yq7SMCeHAl3Bl8c+P6mXfmatjjxEpVmrzRuzKMPd/MRGpy2B/glkuyO4wZZazow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/lefthook-freebsd-x64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.6.1.tgz", + "integrity": "sha512-/NBjMUtnwvdc/p821sfPnZCbWZ6FQkAvnvjoaQu6tkajKZbZYSKsl7UtAicO0nT+79BQFt7TbaZjpua2T9tM5w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/lefthook-linux-arm64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-1.6.1.tgz", + "integrity": "sha512-ke+2ni/bmxgYJSRsH+uIYYfTLj2It7WP+mcF4rfJHRbzn5yDYIjFgylUMC2CgW5urS4DSbxcRIbAqLY3OXAHnw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/lefthook-linux-x64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-1.6.1.tgz", + "integrity": "sha512-/HLkl9jt3XRjT0RPaLpAgUQmvp4zV/KKZ/8x6xslPl89krv3ZkHKKrqeaHdhiengq3hzx3N+KbOfFcxBRzdT6A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/lefthook-windows-arm64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-1.6.1.tgz", + "integrity": "sha512-RyQ8S4/45BpJpRPy7KsOuJeXQ5FOa7MASoPtOYvrXt4A8kayCv1jlGs7MTv3XJbUosCJhfNpw3ReeHVGfw1KIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/lefthook-windows-x64": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-1.6.1.tgz", + "integrity": "sha512-poYLk2tfg1Ncr4aZeFuhHjv1qH6f9hX3tV1FOK2MfWkXkRTYPl6MF5h/ONMIv71BsLjGbAA7LNXM5Mj4/B//lQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/less": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "dependencies": { + "klona": "^2.0.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } + } + }, + "node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/luxon": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz", + "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string": { + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/make-fetch-happen": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", + "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "dev": true, + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/needle": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", + "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/ngx-toastr": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-16.2.0.tgz", + "integrity": "sha512-7X6UhOKiaUeC2eTOsUqctZH0ZWKG8VlzDxWJhdEF1N3kPod46SU/Vn2l0hbt8EDwTjxHKfKyevU2idkYDoZYog==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=14.0.0-0", + "@angular/core": ">=14.0.0-0", + "@angular/platform-browser": ">=14.0.0-0" + } + }, + "node_modules/ngx-webstorage-service": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ngx-webstorage-service/-/ngx-webstorage-service-5.0.0.tgz", + "integrity": "sha512-adipYzdVGA1HxPF5n62eJoQGohiJRlpCp7lPuNQcOvkHGfFUByAfXZHmmLFzb5OFfeNWh1XZ8M2qppbC5uNXFQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": ">=13.0.0" + } + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", + "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true, + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-machine-id": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", + "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-packlist": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", + "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "dev": true, + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", + "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz", + "integrity": "sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nx": { + "version": "17.2.8", + "resolved": "https://registry.npmjs.org/nx/-/nx-17.2.8.tgz", + "integrity": "sha512-rM5zXbuXLEuqQqcjVjClyvHwRJwt+NVImR2A6KFNG40Z60HP6X12wAxxeLHF5kXXTDRU0PFhf/yACibrpbPrAw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "17.2.8", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.5.1", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "3.0.5", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "semver": "7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "17.2.8", + "@nx/nx-darwin-x64": "17.2.8", + "@nx/nx-freebsd-x64": "17.2.8", + "@nx/nx-linux-arm-gnueabihf": "17.2.8", + "@nx/nx-linux-arm64-gnu": "17.2.8", + "@nx/nx-linux-arm64-musl": "17.2.8", + "@nx/nx-linux-x64-gnu": "17.2.8", + "@nx/nx-linux-x64-musl": "17.2.8", + "@nx/nx-win32-arm64-msvc": "17.2.8", + "@nx/nx-win32-x64-msvc": "17.2.8" + }, + "peerDependencies": { + "@swc-node/register": "^1.6.7", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/nx/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nx/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/nx/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nx/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/nx/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nx/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/nx/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nx/node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nx/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/nx/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nx/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nx/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nx/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.5.tgz", + "integrity": "sha512-TAE0m20zSDMnchPja9vtQjri19X3pZIyRpm2TJVeI+yU42leJBBDTRYhOcWFsPhaMxf+3iwQkFiKz16G9AEeeA==", + "dev": true, + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/parse-json/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "devOptional": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dev": true, + "dependencies": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", + "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/piscina": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.2.1.tgz", + "integrity": "sha512-LShp0+lrO+WIzB9LXO+ZmO4zGHxtTJNZhEO56H9SSu+JPaUQb6oLcTCzWi5IL2DS8/vIkCE88ElahuSSw4TAkA==", + "dev": true, + "dependencies": { + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0" + }, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss": { + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", + "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", + "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/preact": { + "version": "10.12.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz", + "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-java": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-2.5.0.tgz", + "integrity": "sha512-6Uc1yHVrLTwgl7D9hsBS3Xa2qXXlEd4v/6z1oio7u8O6mQdh/6cP0cbhS1daik9tNSMMES/VyzI+78918KRuGA==", + "dev": true, + "dependencies": { + "java-parser": "2.2.0", + "lodash": "4.17.21", + "prettier": "3.0.3" + } + }, + "node_modules/prettier-plugin-java/node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz", + "integrity": "sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==", + "dev": true, + "peerDependencies": { + "@volar/vue-language-plugin-pug": "^1.0.4", + "@volar/vue-typescript": "^1.0.4", + "prettier": ">=2.0", + "typescript": ">=2.9" + }, + "peerDependenciesMeta": { + "@volar/vue-language-plugin-pug": { + "optional": true + }, + "@volar/vue-typescript": { + "optional": true + } + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ramda": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", + "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-package-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", + "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", + "dev": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", + "dev": true + }, + "node_modules/regexp-to-ast": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.4.0.tgz", + "integrity": "sha512-4qf/7IsIKfSNHQXSwial1IFmfM1Cc/whNBQqRwe0V2stPe7KmN1U0tWQiIx6JiirgSrisjE0eECdNf7Tav1Ntw==", + "dev": true + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", + "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.6", + "@rollup/rollup-android-arm64": "4.9.6", + "@rollup/rollup-darwin-arm64": "4.9.6", + "@rollup/rollup-darwin-x64": "4.9.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", + "@rollup/rollup-linux-arm64-gnu": "4.9.6", + "@rollup/rollup-linux-arm64-musl": "4.9.6", + "@rollup/rollup-linux-riscv64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-gnu": "4.9.6", + "@rollup/rollup-linux-x64-musl": "4.9.6", + "@rollup/rollup-win32-arm64-msvc": "4.9.6", + "@rollup/rollup-win32-ia32-msvc": "4.9.6", + "@rollup/rollup-win32-x64-msvc": "4.9.6", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sass": { + "version": "1.69.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz", + "integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", + "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", + "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", + "dev": true, + "optional": true + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sigstore": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.2.0.tgz", + "integrity": "sha512-fcU9clHwEss2/M/11FFM8Jwc4PjBgbhXoNskoK5guoK0qGQBSeUbQZRJ+B2fDFIvhyf0gqCaPrel9mszbhAxug==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1", + "@sigstore/sign": "^2.2.1", + "@sigstore/tuf": "^2.3.0", + "@sigstore/verify": "^0.1.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", + "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.17.1" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", + "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "bin": { + "sl-log-transformer": "bin/sl-log-transformer.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/terser": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz", + "integrity": "sha512-d+3WxW4r8WQy2cZWpNRPPGExX8ffOLGcIhheUANKbL5Sqjbhkneki76fRAWeXkaslV2etTb4tSJBSxOsH5+CJw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-toolbelt": { + "version": "6.15.5", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", + "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tuf-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.0.tgz", + "integrity": "sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==", + "dev": true, + "dependencies": { + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", + "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.2.1.tgz", + "integrity": "sha512-7Wa9thEM6/LMnnKtxJHlc8SrTlDmxqJecgz1iy8KlsN0/iskQXOQCuPkrZLXbElPaSw5slFFyKIKXyJ3UtbApw==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz", + "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "is-plain-object": "^5.0.0", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", + "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", + "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", + "dev": true, + "dependencies": { + "typed-assert": "^1.0.8" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", + "webpack": "^5.12.0" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zone.js": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.3.tgz", + "integrity": "sha512-jYoNqF046Q+JfcZSItRSt+oXFcpXL88yq7XAZjb/NKTS7w2hHpKjRJ3VlFD1k75wMaRRXNUt5vrZVlygiMyHbA==", + "dependencies": { + "tslib": "^2.3.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..1f9ac85cb2 --- /dev/null +++ b/package.json @@ -0,0 +1,82 @@ +{ + "name": "exam", + "version": "6.3.0", + "description": "EXAM – electronic exam software for higher education", + "repository": { + "type": "git", + "url": " https://github.com/CSCfi/exam.git" + }, + "license": "EUPL-1.1", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build --build-optimizer false --output-path ./public", + "analyze": "ng build --stats-json && webpack-bundle-analyzer dist/exam/stats.json", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "lint": "ng lint --fix", + "format": "prettier --write \"ui/src/app/**/*.{ts,html}\" --write \"{app,test}/**/*.java\" --plugin=prettier-plugin-java --print-width=120 --tab-width=4; exit 0", + "prepare": "lefthook install", + "check-format": "prettier --check \"ui/src/app/**/*.{ts,html}\" --check \"{app,test}/**/*.java\" --plugin=prettier-plugin-java --print-width=120 --tab-width=4; exit 0", + "check-lint": "ng lint" + }, + "dependencies": { + "@angular/animations": "^17.0.9", + "@angular/cdk": "^17.0.0", + "@angular/common": "^17.0.9", + "@angular/compiler": "^17.0.9", + "@angular/core": "^17.0.9", + "@angular/forms": "^17.0.9", + "@angular/localize": "^17.0.9", + "@angular/platform-browser": "^17.0.9", + "@angular/platform-browser-dynamic": "^17.0.9", + "@angular/router": "^17.0.9", + "@fullcalendar/angular": "^6.0.3", + "@fullcalendar/luxon2": "^6.0.3", + "@fullcalendar/timegrid": "^6.0.3", + "@ng-bootstrap/ng-bootstrap": "^16.0.0", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@popperjs/core": "^2.10.2", + "bootstrap": "^5.3.2", + "bootstrap-icons": "^1.3.0", + "chart.js": "^3.8.0", + "chartjs-plugin-datalabels": "^2.0.0", + "date-fns": "^2.25.0", + "file-saver-es": "^2.0.5", + "luxon": "^2.0.0", + "ngx-toastr": "^16.0.2", + "ngx-webstorage-service": "^5.0.0", + "ramda": "^0.28.0", + "rxjs": "^7.4.0", + "zone.js": "^0.14.3" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.0.10", + "@angular-eslint/builder": "^17.2.0", + "@angular-eslint/eslint-plugin": "^17.2.0", + "@angular-eslint/eslint-plugin-template": "^17.2.0", + "@angular-eslint/schematics": "^17.2.0", + "@angular-eslint/template-parser": "^17.2.0", + "@angular/cli": "^17.0.10", + "@angular/compiler-cli": "^17.0.9", + "@types/ckeditor": "^4.9.10", + "@types/file-saver-es": "^2.0.1", + "@types/jasmine": "^3.10.0", + "@types/luxon": "^3.1.0", + "@types/mathjax": "^0.0.37", + "@types/ramda": "^0.28.14", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "@typescript-eslint/parser": "^6.10.0", + "eslint": "^8.53.0", + "eslint-plugin-deprecation": "^2.0.0", + "eslint-plugin-no-relative-import-paths": "^1.5.4", + "karma": "^6.3.0", + "lefthook": "^1.6.1", + "prettier": "^3.0.0", + "prettier-plugin-java": "^2.5.0", + "prettier-plugin-organize-imports": "^3.2.4", + "typescript": "~5.3.0", + "webpack-bundle-analyzer": "^4.5.0" + } +} diff --git a/project/build.properties b/project/build.properties index 742d2e0442..27430827bc 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.11 +sbt.version=1.9.6 diff --git a/project/plugins.sbt b/project/plugins.sbt index 1c10f9a45f..28c19239b8 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,11 @@ -resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/" +addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.2") -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.16") +addSbtPlugin("org.playframework" % "sbt-play-ebean" % "8.0.0") + +addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1") + +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") + +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.12.1") -addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "6.0.0") -// addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1") diff --git a/scripts/internal/bump_version.sh b/scripts/internal/bump_version.sh index 01dc46303c..956a45ba8f 100644 --- a/scripts/internal/bump_version.sh +++ b/scripts/internal/bump_version.sh @@ -14,9 +14,9 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ${SED} -i "s/version := .*/version := \"$1\"/g" "${DIR}/../../build.sbt" ${SED} -i "s/exam.release.version = .*/exam.release.version = \"$1\"/g" "${DIR}/../../conf/application.conf" -${SED} -i "s/\"version\": .*/\"version\": \"$1\",/g" "${DIR}/../../ui/package.json" +${SED} -i "s/\"version\": .*/\"version\": \"$1\",/g" "${DIR}/../../package.json" -npm i --prefix ui +npm i echo "Version bumped to $1" exit 0; diff --git a/test/backend/util/JsonFilterTest.java b/test/backend/util/JsonFilterTest.java index 56357f4386..8011f37f84 100644 --- a/test/backend/util/JsonFilterTest.java +++ b/test/backend/util/JsonFilterTest.java @@ -29,6 +29,7 @@ import org.apache.commons.io.FileUtils; import org.junit.Test; import play.libs.Json; +import scala.jdk.javaapi.CollectionConverters; import util.json.JsonFilter; public class JsonFilterTest { @@ -54,7 +55,11 @@ public void testFilterProperties() throws Exception { offers.forEach(offer -> assertThatJsonHasProperties(offer, filters)); // Filter json - JsonFilter.filterProperties(node1, true, Collections.emptySet(), filters); + JsonFilter.filterProperties( + node1, + CollectionConverters.asScala(Collections.emptySet()).toSet(), + CollectionConverters.asScala(Arrays.asList(filters)).toSeq() + ); // Check that node1 does not have properties assertThatJsonDoesNotHaveProperties(node1, filters); @@ -78,7 +83,11 @@ public void testFilterPropertiesWithIds() throws Exception { // Filter json final Set ids = new HashSet<>(); ids.add(2L); - JsonFilter.filterProperties(root, true, ids, filters); + JsonFilter.filterProperties( + root, + CollectionConverters.asScala(ids).toSet(), + CollectionConverters.asScala(Arrays.asList(filters)).toSeq() + ); final ArrayNode array = (ArrayNode) root; final JsonNode node1 = array.get(0); diff --git a/test/base/DropAllDdlGenerator.java b/test/base/DropAllDdlGenerator.java deleted file mode 100644 index 496d68dd92..0000000000 --- a/test/base/DropAllDdlGenerator.java +++ /dev/null @@ -1,16 +0,0 @@ -package base; - -import io.ebean.config.ServerConfig; -import io.ebeaninternal.api.SpiEbeanServer; -import io.ebeaninternal.dbmigration.DdlGenerator; - -public class DropAllDdlGenerator extends DdlGenerator { - - public DropAllDdlGenerator(SpiEbeanServer server, ServerConfig serverConfig) { - super(server, serverConfig); - } - - public String generateDropDdl() { - return generateDropAllDdl(); - } -} diff --git a/test/base/IntegrationTestCase.java b/test/base/IntegrationTestCase.java index 8a88d67543..570d34bc21 100644 --- a/test/base/IntegrationTestCase.java +++ b/test/base/IntegrationTestCase.java @@ -8,7 +8,8 @@ import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.PathNotFoundException; -import io.ebean.Ebean; +import io.ebean.DB; +import jakarta.persistence.PersistenceException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -24,7 +25,6 @@ import java.util.Map; import java.util.Objects; import java.util.TreeSet; -import javax.persistence.PersistenceException; import javax.validation.constraints.NotNull; import models.Attachment; import models.Exam; @@ -44,6 +44,7 @@ import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.inspector.TrustedTagInspector; import org.yaml.snakeyaml.representer.Representer; import play.Application; import play.inject.guice.GuiceApplicationBuilder; @@ -69,7 +70,7 @@ public IntegrationTestCase() { HAKA_HEADERS.put("displayName", "George%20Lazenby"); HAKA_HEADERS.put("eppn", "george.lazenby@funet.fi"); HAKA_HEADERS.put("sn", "Lazenby"); - HAKA_HEADERS.put("preferredLanguage", "fi"); + HAKA_HEADERS.put("preferredLanguage", "de"); // use an unsupported UI language HAKA_HEADERS.put("Shib-Session-ID", "_5d9a583a894275c15edef02c5602c4d7"); HAKA_HEADERS.put("mail", "glazenby%40funet.fi"); HAKA_HEADERS.put("unscoped-affiliation", "member;employee;faculty"); @@ -257,7 +258,7 @@ protected void initExamSectionQuestions(Exam exam) { .stream() .map(ExamInspection::getUser) .forEach(u -> { - u.setLanguage(Ebean.find(Language.class, "en")); + u.setLanguage(DB.find(Language.class, "en")); u.update(); }); exam @@ -303,7 +304,7 @@ private boolean isIndefinite(String path) { private void addTestData() throws Exception { int userCount; try { - userCount = Ebean.find(User.class).findCount(); + userCount = DB.find(User.class).findCount(); } catch (PersistenceException e) { // Tables are likely not there yet, skip this. return; @@ -311,42 +312,44 @@ private void addTestData() throws Exception { if (userCount == 0) { LoaderOptions options = new LoaderOptions(); options.setMaxAliasesForCollections(400); - Yaml yaml = new Yaml(new JodaPropertyConstructor(), new Representer(), new DumperOptions(), options); + options.setTagInspector(new TrustedTagInspector()); + Yaml yaml = new Yaml(new JodaPropertyConstructor(options), new Representer(new DumperOptions())); + //Yaml yaml = new Yaml(new JodaPropertyConstructor(), new Representer(new DumperOptions()), new DumperOptions(), options); InputStream is = new FileInputStream(new File("test/resources/initial-data.yml")); Map> all = yaml.load(is); is.close(); - Ebean.saveAll(all.get("role")); - Ebean.saveAll(all.get("exam-type")); - Ebean.saveAll(all.get("exam-execution-type")); - Ebean.saveAll(all.get("languages")); - Ebean.saveAll(all.get("organisations")); - Ebean.saveAll(all.get("attachments")); - Ebean.saveAll(all.get("users")); - Ebean.saveAll(all.get("grade-scales")); - Ebean.saveAll(all.get("grades")); - Ebean.saveAll(all.get("question-essay")); - Ebean.saveAll(all.get("question-multiple-choice")); - Ebean.saveAll(all.get("question-weighted-multiple-choice")); - Ebean.saveAll(all.get("question-claim-choice")); - Ebean.saveAll(all.get("question-clozetest")); - Ebean.saveAll(all.get("softwares")); - Ebean.saveAll(all.get("courses")); - Ebean.saveAll(all.get("comments")); + DB.saveAll(all.get("role")); + DB.saveAll(all.get("exam-type")); + DB.saveAll(all.get("exam-execution-type")); + DB.saveAll(all.get("languages")); + DB.saveAll(all.get("organisations")); + DB.saveAll(all.get("attachments")); + DB.saveAll(all.get("users")); + DB.saveAll(all.get("grade-scales")); + DB.saveAll(all.get("grades")); + DB.saveAll(all.get("question-essay")); + DB.saveAll(all.get("question-multiple-choice")); + DB.saveAll(all.get("question-weighted-multiple-choice")); + DB.saveAll(all.get("question-claim-choice")); + DB.saveAll(all.get("question-clozetest")); + DB.saveAll(all.get("softwares")); + DB.saveAll(all.get("courses")); + DB.saveAll(all.get("comments")); for (Object o : all.get("exams")) { Exam e = (Exam) o; e.generateHash(); e.save(); } - Ebean.saveAll(all.get("exam-sections")); - Ebean.saveAll(all.get("section-questions")); - Ebean.saveAll(all.get("exam-participations")); - Ebean.saveAll(all.get("exam-inspections")); - Ebean.saveAll(all.get("mail-addresses")); - Ebean.saveAll(all.get("calendar-events")); - Ebean.saveAll(all.get("exam-rooms")); - Ebean.saveAll(all.get("exam-machines")); - Ebean.saveAll(all.get("exam-room-reservations")); - Ebean.saveAll(all.get("exam-enrolments")); + DB.saveAll(all.get("exam-sections")); + DB.saveAll(all.get("section-questions")); + DB.saveAll(all.get("exam-participations")); + DB.saveAll(all.get("exam-inspections")); + DB.saveAll(all.get("mail-addresses")); + DB.saveAll(all.get("calendar-events")); + DB.saveAll(all.get("exam-rooms")); + DB.saveAll(all.get("exam-machines")); + DB.saveAll(all.get("exam-room-reservations")); + DB.saveAll(all.get("exam-enrolments")); } } @@ -367,7 +370,7 @@ protected Attachment createAttachment(String fileName, String filePath, String m } protected User getLoggerUser() { - return Ebean.find(User.class, userId); + return DB.find(User.class, userId); } @NotNull diff --git a/test/base/JodaPropertyConstructor.java b/test/base/JodaPropertyConstructor.java index e26e5000f7..4f1982f9c0 100644 --- a/test/base/JodaPropertyConstructor.java +++ b/test/base/JodaPropertyConstructor.java @@ -3,15 +3,21 @@ import java.util.Date; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.constructor.Construct; import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.inspector.TrustedTagInspector; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.NodeId; import org.yaml.snakeyaml.nodes.Tag; class JodaPropertyConstructor extends Constructor { - JodaPropertyConstructor() { + /*JodaPropertyConstructor() { + yamlClassConstructors.put(NodeId.scalar, new TimeStampConstruct()); + }*/ + JodaPropertyConstructor(LoaderOptions options) { + super(options); yamlClassConstructors.put(NodeId.scalar, new TimeStampConstruct()); } diff --git a/test/controllers/CalendarControllerTest.java b/test/controllers/CalendarControllerTest.java index 271413d232..e0109bad9e 100644 --- a/test/controllers/CalendarControllerTest.java +++ b/test/controllers/CalendarControllerTest.java @@ -9,12 +9,12 @@ import com.icegreen.greenmail.junit4.GreenMailRule; import com.icegreen.greenmail.util.GreenMailUtil; import com.icegreen.greenmail.util.ServerSetupTest; -import io.ebean.Ebean; +import io.ebean.DB; +import jakarta.mail.internet.MimeMessage; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; -import javax.mail.internet.MimeMessage; import models.Exam; import models.ExamEnrolment; import models.ExamExecutionType; @@ -54,7 +54,8 @@ private void setWorkingHours() { dwh.setWeekday(d); dwh.setRoom(room); dwh.setStartTime(DateTime.now().withTimeAtStartOfDay()); - dwh.setEndTime(DateTime.now().withTime(23, 59, 59, 999)); + dwh.setEndTime(dwh.getStartTime().withTime(20, 59, 59, 999)); + dwh.setTimezoneOffset(7200000); dwh.save(); }); } @@ -63,12 +64,12 @@ private void setWorkingHours() { @Before public void setUp() throws Exception { super.setUp(); - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); - exam = Ebean.find(Exam.class).where().eq("state", Exam.State.PUBLISHED).findList().get(0); - user = Ebean.find(User.class, userId); - user.setLanguage(Ebean.find(Language.class, "en")); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); + exam = DB.find(Exam.class).where().eq("state", Exam.State.PUBLISHED).findList().get(0); + user = DB.find(User.class, userId); + user.setLanguage(DB.find(Language.class, "en")); user.update(); - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setRoomInstructionEN("information in English here"); room.update(); setWorkingHours(); @@ -84,8 +85,8 @@ public void setUp() throws Exception { @Test @RunAsStudent public void testConcurrentCreateReservation() throws Exception { - exam.setExecutionType(Ebean.find(ExamExecutionType.class, 2)); - exam.getExamOwners().add(Ebean.find(User.class, 4)); + exam.setExecutionType(DB.find(ExamExecutionType.class, 2)); + exam.getExamOwners().add(DB.find(User.class, 4)); exam.save(); DateTime start = DateTime .now() @@ -128,7 +129,7 @@ public void testConcurrentCreateReservation() throws Exception { assertThat(status).containsOnly(200); greenMail.purgeEmailFromAllMailboxes(); assertThat(greenMail.waitForIncomingEmail(MAIL_TIMEOUT, callCount)).isTrue(); - final int count = Ebean.find(Reservation.class).where().eq("user.id", 3L).findCount(); + final int count = DB.find(Reservation.class).where().eq("user.id", 3L).findCount(); assertThat(count).isEqualTo(1); } @@ -137,8 +138,8 @@ public void testConcurrentCreateReservation() throws Exception { public void testCreateReservation() throws Exception { // Setup // Private exam - exam.setExecutionType(Ebean.find(ExamExecutionType.class, 2)); - exam.getExamOwners().add(Ebean.find(User.class, 4)); + exam.setExecutionType(DB.find(ExamExecutionType.class, 2)); + exam.getExamOwners().add(DB.find(User.class, 4)); exam.save(); DateTime start = DateTime .now() @@ -169,7 +170,7 @@ public void testCreateReservation() throws Exception { assertThat(result.status()).isEqualTo(200); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNotNull(); assertThat(ee.getReservation().getStartAt()).isEqualTo(start); assertThat(ee.getReservation().getEndAt()).isEqualTo(end); @@ -186,7 +187,7 @@ public void testCreateReservation() throws Exception { assertThat(body).contains("You have booked an exam time"); assertThat(body).contains("information in English here"); assertThat(body).contains(room.getName()); - assertThat(GreenMailUtil.hasNonTextAttachments(mails[0])).isTrue(); + //assertThat(GreenMailUtil.hasNonTextAttachments(mails[0])).isTrue(); } @Test @@ -229,7 +230,7 @@ public void testCreateReservationPreviousInFuture() throws Exception { assertThat(result.status()).isEqualTo(200); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNotNull(); assertThat(ee.getReservation().getStartAt()).isEqualTo(start); assertThat(ee.getReservation().getEndAt()).isEqualTo(end); @@ -245,7 +246,7 @@ public void testCreateReservationPreviousInFuture() throws Exception { assertThat(body).contains("You have booked an exam time"); assertThat(body).contains("information in English here"); assertThat(body).contains(room.getName()); - assertThat(GreenMailUtil.hasNonTextAttachments(mails[0])).isTrue(); + //assertThat(GreenMailUtil.hasNonTextAttachments(mails[0])).isTrue(); } @Test @@ -296,7 +297,7 @@ public void testCreateReservationPreviousInPast() throws Exception { assertThat(result.status()).isEqualTo(200); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, newEnrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, newEnrolment.getId()); assertThat(ee.getReservation()).isNotNull(); assertThat(ee.getReservation().getStartAt()).isEqualTo(start); assertThat(ee.getReservation().getEndAt()).isEqualTo(end); @@ -312,7 +313,7 @@ public void testCreateReservationPreviousInPast() throws Exception { assertThat(body).contains("You have booked an exam time"); assertThat(body).contains("information in English here"); assertThat(body).contains(room.getName()); - assertThat(GreenMailUtil.hasNonTextAttachments(mails[0])).isTrue(); + //assertThat(GreenMailUtil.hasNonTextAttachments(mails[0])).isTrue(); } @Test @@ -336,7 +337,7 @@ public void testCreateReservationStartIsPast() throws Exception { assertThat(result.status()).isEqualTo(400); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNull(); } @@ -361,7 +362,7 @@ public void testCreateReservationEndsBeforeStarts() throws Exception { assertThat(result.status()).isEqualTo(400); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNull(); } @@ -391,10 +392,10 @@ public void testCreateReservationPreviousInEffect() throws Exception { .put("end", ISODateTimeFormat.dateTime().print(end)) ); assertThat(result.status()).isEqualTo(403); - assertThat(contentAsString(result).equals("sitnet_error_enrolment_not_found")); + assertThat(contentAsString(result).equals("i18n_error_enrolment_not_found")); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation().getId()).isEqualTo(reservation.getId()); } @@ -415,9 +416,9 @@ public void testRemoveReservation() throws Exception { assertThat(greenMail.waitForIncomingEmail(MAIL_TIMEOUT, 1)).isTrue(); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNull(); - assertThat(Ebean.find(Reservation.class, reservation.getId())).isNull(); + assertThat(DB.find(Reservation.class, reservation.getId())).isNull(); } @Test @@ -436,7 +437,7 @@ public void testRemoveReservationInPast() throws Exception { assertThat(result.status()).isEqualTo(403); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation().getId()).isEqualTo(reservation.getId()); } @@ -456,7 +457,7 @@ public void testRemoveReservationInProgress() throws Exception { assertThat(result.status()).isEqualTo(403); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation().getId()).isEqualTo(reservation.getId()); } } diff --git a/test/controllers/EnrolmentControllerTest.java b/test/controllers/EnrolmentControllerTest.java index f85d25201a..1101476f78 100644 --- a/test/controllers/EnrolmentControllerTest.java +++ b/test/controllers/EnrolmentControllerTest.java @@ -1,5 +1,8 @@ package controllers; +import static org.fest.assertions.Assertions.assertThat; +import static play.test.Helpers.contentAsString; + import base.IntegrationTestCase; import base.RunAsStudent; import base.RunAsTeacher; @@ -10,7 +13,7 @@ import com.icegreen.greenmail.junit4.GreenMailRule; import com.icegreen.greenmail.util.ServerSetupTest; import helpers.RemoteServerHelper; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.json.EJson; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -30,7 +33,6 @@ import models.json.ExternalExam; import net.jodah.concurrentunit.Waiter; import org.eclipse.jetty.server.Server; -import static org.fest.assertions.Assertions.assertThat; import org.joda.time.DateTime; import org.junit.AfterClass; import org.junit.Before; @@ -40,7 +42,6 @@ import play.libs.Json; import play.mvc.Result; import play.test.Helpers; -import static play.test.Helpers.contentAsString; import util.json.JsonDeserializer; public class EnrolmentControllerTest extends IntegrationTestCase { @@ -55,7 +56,7 @@ public class EnrolmentControllerTest extends IntegrationTestCase { @Rule public final com.icegreen.greenmail.junit4.GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP) - .withConfiguration(new GreenMailConfiguration().withDisabledAuthentication()); + .withConfiguration(new GreenMailConfiguration().withDisabledAuthentication()); public static class CourseInfoServlet extends HttpServlet { @@ -83,15 +84,15 @@ public static void shutdownServer() throws Exception { @Before public void setUp() throws Exception { super.setUp(); - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); - exam = Ebean.find(Exam.class, 1); - user = Ebean.find(User.class, userId); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); + exam = DB.find(Exam.class, 1); + user = DB.find(User.class, userId); enrolment = new ExamEnrolment(); enrolment.setExam(exam); enrolment.setUser(user); reservation = new Reservation(); reservation.setUser(user); - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); } @Test @@ -100,7 +101,7 @@ public void testPreEnrollWithEmail() throws Exception { String eppn = "student@uni.org"; String email = "student@foo.bar"; exam.setExecutionType( - Ebean.find(ExamExecutionType.class).where().eq("type", ExamExecutionType.Type.PRIVATE.toString()).findOne() + DB.find(ExamExecutionType.class).where().eq("type", ExamExecutionType.Type.PRIVATE.toString()).findOne() ); exam.update(); @@ -111,12 +112,12 @@ public void testPreEnrollWithEmail() throws Exception { ); assertThat(result.status()).isEqualTo(200); - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login(eppn, ImmutableMap.of("mail", email)); - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, exam.getExamEnrolments().get(0).getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, exam.getExamEnrolments().get(0).getId()); assertThat(ee.getUser().getEmail()).isEqualTo(email); assertThat(ee.getPreEnrolledUserEmail()).isNull(); @@ -128,7 +129,7 @@ public void testPreEnrollWithEmail() throws Exception { public void testPreEnrollWithEppn() throws Exception { String eppn = "student@uni.org"; exam.setExecutionType( - Ebean.find(ExamExecutionType.class).where().eq("type", ExamExecutionType.Type.PRIVATE.toString()).findOne() + DB.find(ExamExecutionType.class).where().eq("type", ExamExecutionType.Type.PRIVATE.toString()).findOne() ); exam.update(); @@ -139,12 +140,12 @@ public void testPreEnrollWithEppn() throws Exception { ); assertThat(result.status()).isEqualTo(200); - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login(eppn); - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, exam.getExamEnrolments().get(0).getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, exam.getExamEnrolments().get(0).getId()); assertThat(ee.getUser().getEppn()).isEqualTo(eppn); assertThat(ee.getPreEnrolledUserEmail()).isNull(); @@ -197,7 +198,7 @@ public void testCreateEnrolment() throws Exception { assertThat(result.status()).isEqualTo(200); // Verify - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .eq("exam.id", exam.getId()) @@ -228,7 +229,7 @@ public void testConcurentCreateEnrolment() throws Exception { ); waiter.await(5000, callCount); - final int count = Ebean + final int count = DB .find(ExamEnrolment.class) .where() .eq("exam.id", exam.getId()) @@ -252,10 +253,10 @@ public void testRecreateEnrolment() throws Exception { Json.newObject().put("code", exam.getCourse().getCode()) ); assertThat(result.status()).isEqualTo(403); - assertThat(contentAsString(result)).isEqualTo("sitnet_error_enrolment_exists"); + assertThat(contentAsString(result)).isEqualTo("i18n_error_enrolment_exists"); // Verify - List enrolments = Ebean.find(ExamEnrolment.class).findList(); + List enrolments = DB.find(ExamEnrolment.class).findList(); assertThat(enrolments).hasSize(1); enrolment = enrolments.get(0); assertThat(enrolment.getEnrolledOn()).isEqualTo(enrolledOn); @@ -284,7 +285,7 @@ public void testCreateEnrolmentFutureReservationExists() throws Exception { assertThat(result.status()).isEqualTo(200); // Verify - List enrolments = Ebean.find(ExamEnrolment.class).findList(); + List enrolments = DB.find(ExamEnrolment.class).findList(); assertThat(enrolments).hasSize(1); ExamEnrolment e = enrolments.get(0); assertThat(e.getEnrolledOn().isAfter(enrolledOn)); @@ -312,10 +313,10 @@ public void testCreateEnrolmentOngoingReservationExists() throws Exception { Json.newObject().put("code", exam.getCourse().getCode()) ); assertThat(result.status()).isEqualTo(403); // Not found - assertThat(contentAsString(result)).isEqualTo("sitnet_reservation_in_effect"); + assertThat(contentAsString(result)).isEqualTo("i18n_reservation_in_effect"); // Verify - List enrolments = Ebean.find(ExamEnrolment.class).findList(); + List enrolments = DB.find(ExamEnrolment.class).findList(); assertThat(enrolments).hasSize(1); ExamEnrolment e = enrolments.get(0); assertThat(e.getEnrolledOn()).isEqualTo(enrolledOn); @@ -343,7 +344,7 @@ public void testCreateEnrolmentPastReservationExists() throws Exception { assertThat(result.status()).isEqualTo(200); // Verify - List enrolments = Ebean.find(ExamEnrolment.class).findList(); + List enrolments = DB.find(ExamEnrolment.class).findList(); assertThat(enrolments).hasSize(2); ExamEnrolment e = enrolments.get(1); assertThat(e.getEnrolledOn().isAfter(enrolledOn)); diff --git a/test/controllers/EnrolmentInterfaceTest.java b/test/controllers/EnrolmentInterfaceTest.java index 9b36740eb9..0a08e347c6 100644 --- a/test/controllers/EnrolmentInterfaceTest.java +++ b/test/controllers/EnrolmentInterfaceTest.java @@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableMap; import helpers.RemoteServerHelper; -import io.ebean.Ebean; +import io.ebean.DB; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -55,14 +55,14 @@ public void setUp() throws Exception { super.setUp(); // Fake API shall return a course with code 810136P. Lets make a referenced exam active in the DB so it should // pop up in the search results - Exam exam = Ebean + Exam exam = DB .find(Exam.class) .where() .eq("course.code", "810136P") .eq("state", Exam.State.PUBLISHED) .findOne(); - exam.setExamActiveStartDate(DateTime.now().minusDays(1)); - exam.setExamActiveEndDate(DateTime.now().plusDays(1)); + exam.setPeriodStart(DateTime.now().minusDays(1)); + exam.setPeriodEnd(DateTime.now().plusDays(1)); exam.save(); } diff --git a/test/controllers/ExamControllerTest.java b/test/controllers/ExamControllerTest.java index 18d24468f7..bbfec8c421 100644 --- a/test/controllers/ExamControllerTest.java +++ b/test/controllers/ExamControllerTest.java @@ -10,7 +10,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -37,26 +37,24 @@ public void testGetActiveExamsUnauthorized() { @RunAsTeacher public void testGetActiveExams() { // Setup - List activeExams = Ebean + List activeExams = DB .find(Exam.class) .where() .eq("creator.id", userId) .in("state", Exam.State.PUBLISHED, Exam.State.SAVED, Exam.State.DRAFT) .findList(); - activeExams.forEach( - e -> { - e.getExamOwners().add(e.getCreator()); - e.update(); - } - ); + activeExams.forEach(e -> { + e.getExamOwners().add(e.getCreator()); + e.update(); + }); Set ids = new HashSet<>(); for (Exam e : activeExams) { - e.setExamActiveStartDate(DateTime.now()); - e.setExamActiveEndDate(DateTime.now().plusWeeks(1)); + e.setPeriodStart(DateTime.now()); + e.setPeriodEnd(DateTime.now().plusWeeks(1)); e.update(); ids.add(e.getId()); } - String[] expectedPaths = { "id", "name", "course.code", "examActiveStartDate", "examActiveEndDate" }; + String[] expectedPaths = { "id", "name", "course.code", "periodStart", "periodEnd" }; // Execute Result result = get("/app/reviewerexams"); @@ -69,8 +67,8 @@ public void testGetActiveExams() { assertPathsExist(node, jsonPaths(expectedPaths, exams.size())); for (JsonNode n : exams) { Exam e = deserialize(Exam.class, n); - assertThat(e.getExamActiveEndDate().isAfterNow()); - assertThat(e.getExamActiveStartDate().isBeforeNow()); + assertThat(e.getPeriodEnd().isAfterNow()); + assertThat(e.getPeriodStart().isBeforeNow()); assertThat(ids.contains(e.getId())); } } @@ -92,7 +90,7 @@ public void testCreateDraftExamUnauthorized() { @RunAsTeacher public void testCreateDraftExam() { // Setup - int originalRowCount = Ebean.find(Exam.class).findCount(); + int originalRowCount = DB.find(Exam.class).findCount(); // Execute Result result = request( @@ -105,7 +103,7 @@ public void testCreateDraftExam() { assertThat(result.status()).isEqualTo(200); JsonNode node = Json.parse(contentAsString(result)); Long id = node.get("id").asLong(); - Exam draft = Ebean.find(Exam.class, id); + Exam draft = DB.find(Exam.class, id); assertThat(draft).isNotNull(); assertThat(draft.getName()).isNull(); assertThat(draft.getCreator().getId()).isEqualTo(userId); @@ -118,9 +116,8 @@ public void testCreateDraftExam() { assertThat(draft.getExamLanguages().size()).isEqualTo(1); assertThat(draft.getExamLanguages().get(0).getCode()).isEqualTo("fi"); assertThat(draft.getExamType().getId()).isEqualTo(2); - assertThat(draft.getExpanded()).isTrue(); assertThat(draft.isAnonymous()).isTrue(); - int rowCount = Ebean.find(Exam.class).findCount(); + int rowCount = DB.find(Exam.class).findCount(); assertThat(rowCount).isEqualTo(originalRowCount + 1); } @@ -129,7 +126,7 @@ public void testCreateDraftExam() { public void testGetExam() throws Exception { // Setup long id = 1L; - Exam expected = Ebean.find(Exam.class, id); + Exam expected = DB.find(Exam.class, id); // Execute Result result = get("/app/exams/" + id); @@ -152,8 +149,8 @@ public void testGetExam() throws Exception { assertThat(expected.getCustomCredit()).isEqualTo(returned.getCustomCredit()); assertThat(expected.getDuration()).isEqualTo(returned.getDuration()); assertThat(expected.getEnrollInstruction()).isEqualTo(returned.getEnrollInstruction()); - assertThat(expected.getExamActiveEndDate()).isEqualTo(returned.getExamActiveEndDate()); - assertThat(expected.getExamActiveStartDate()).isEqualTo(returned.getExamActiveStartDate()); + assertThat(expected.getPeriodEnd()).isEqualTo(returned.getPeriodEnd()); + assertThat(expected.getPeriodStart()).isEqualTo(returned.getPeriodStart()); } @Test @@ -161,7 +158,7 @@ public void testGetExam() throws Exception { public void testGetStudentExamNotAllowed() { // Setup long id = 1L; - Exam expected = Ebean.find(Exam.class, id); + Exam expected = DB.find(Exam.class, id); expected.setState(Exam.State.STUDENT_STARTED); expected.update(); @@ -175,8 +172,8 @@ public void testGetStudentExamNotAllowed() { public void testExamTypeUpdate() throws Exception { // Setup final long id = 1L; - Exam exam = Ebean.find(Exam.class, id); - ExamType examType = Ebean.find(ExamType.class, 1L); + Exam exam = DB.find(Exam.class, id); + ExamType examType = DB.find(ExamType.class, 1L); exam.setExamType(examType); exam.save(); @@ -223,8 +220,8 @@ private String[] getExamFields() { "instruction", "enrollInstruction", "shared", - "examActiveStartDate", - "examActiveEndDate", + "periodStart", + "periodEnd", "duration", "gradeScale", "gradeScale.description", @@ -234,7 +231,6 @@ private String[] getExamFields() { "state", "examFeedback", "creditType", - "expanded", "attachment", }; } diff --git a/test/controllers/ExaminationControllerTest.java b/test/controllers/ExaminationControllerTest.java index e3d67b1130..af2e124437 100644 --- a/test/controllers/ExaminationControllerTest.java +++ b/test/controllers/ExaminationControllerTest.java @@ -12,12 +12,12 @@ import com.icegreen.greenmail.junit4.GreenMailRule; import com.icegreen.greenmail.util.GreenMailUtil; import com.icegreen.greenmail.util.ServerSetupTest; -import io.ebean.Ebean; +import io.ebean.DB; +import jakarta.mail.internet.MimeMessage; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import javax.mail.internet.MimeMessage; import models.AutoEvaluationConfig; import models.Exam; import models.ExamEnrolment; @@ -59,19 +59,13 @@ public class ExaminationControllerTest extends IntegrationTestCase { @Before public void setUp() throws Exception { super.setUp(); - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); exam = - Ebean - .find(Exam.class) - .fetch("examSections") - .fetch("examSections.sectionQuestions") - .where() - .idEq(1L) - .findOne(); + DB.find(Exam.class).fetch("examSections").fetch("examSections.sectionQuestions").where().idEq(1L).findOne(); initExamSectionQuestions(exam); - user = Ebean.find(User.class, userId); - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + user = DB.find(User.class, userId); + ExamRoom room = DB.find(ExamRoom.class, 1L); machine = room.getExamMachines().get(0); machine.setIpAddress("127.0.0.1"); // so that the IP check won't fail machine.update(); @@ -130,11 +124,11 @@ public void testCreateStudentExam() throws Exception { assertThat(studentExam.getDuration()).isEqualTo(exam.getDuration()); - assertThat(Ebean.find(Exam.class).where().eq("hash", studentExam.getHash()).findOne()).isNotNull(); - assertThat(Ebean.find(ExamEnrolment.class, enrolment.getId()).getExam().getHash()) + assertThat(DB.find(Exam.class).where().eq("hash", studentExam.getHash()).findOne()).isNotNull(); + assertThat(DB.find(ExamEnrolment.class, enrolment.getId()).getExam().getHash()) .isEqualTo(studentExam.getHash()); - ExamParticipation participation = Ebean + ExamParticipation participation = DB .find(ExamParticipation.class) .where() .eq("exam.id", studentExam.getId()) @@ -147,7 +141,7 @@ public void testCreateStudentExam() throws Exception { @RunAsStudent public void testAnswerMultiChoiceQuestion() throws Exception { Exam studentExam = prepareExamination(); - ExamSectionQuestion question = Ebean + ExamSectionQuestion question = DB .find(ExamSectionQuestion.class) .where() .eq("examSection.exam", studentExam) @@ -187,7 +181,7 @@ private JsonNode createMultipleChoiceAnswerData(ExamSectionQuestionOption... opt public void testAnswerMultiChoiceQuestionWrongIP() throws Exception { // Setup Exam studentExam = prepareExamination(); - ExamSectionQuestion question = Ebean + ExamSectionQuestion question = DB .find(ExamSectionQuestion.class) .where() .eq("examSection.exam", studentExam) @@ -213,7 +207,7 @@ public void testAnswerMultiChoiceQuestionWrongIP() throws Exception { @RunAsStudent public void testAnswerClozeTestQuestionInvalidJson() throws Exception { Exam studentExam = prepareExamination(); - ExamSectionQuestion question = Ebean + ExamSectionQuestion question = DB .find(ExamSectionQuestion.class) .where() .eq("examSection.exam", studentExam) @@ -279,7 +273,7 @@ public void testDoExamAndAutoEvaluate() throws Exception { assertThat(r.status()).isEqualTo(Helpers.OK); break; default: - ExamSectionQuestion sectionQuestion = Ebean + ExamSectionQuestion sectionQuestion = DB .find(ExamSectionQuestion.class) .where() .eq("examSection.exam", studentExam) @@ -304,7 +298,7 @@ public void testDoExamAndAutoEvaluate() throws Exception { }); Result result = request(Helpers.PUT, String.format("/app/student/exam/%s", studentExam.getHash()), null); assertThat(result.status()).isEqualTo(Helpers.OK); - Exam turnedExam = Ebean.find(Exam.class, studentExam.getId()); + Exam turnedExam = DB.find(Exam.class, studentExam.getId()); assertThat(turnedExam.getGrade()).isNotNull(); assertThat(turnedExam.getState()).isEqualTo(Exam.State.GRADED); @@ -313,7 +307,7 @@ public void testDoExamAndAutoEvaluate() throws Exception { private Exam createPrivateStudentExam() { exam.setExecutionType( - Ebean.find(ExamExecutionType.class).where().eq("type", ExamExecutionType.Type.PRIVATE.toString()).findOne() + DB.find(ExamExecutionType.class).where().eq("type", ExamExecutionType.Type.PRIVATE.toString()).findOne() ); exam.update(); // Execute @@ -369,7 +363,7 @@ public void testCreateStudentExamWrongIP() throws Exception { assertThat(result.status()).isEqualTo(Helpers.FORBIDDEN); // Verify that no student exam was created - assertThat(Ebean.find(Exam.class).where().eq("parent.id", exam.getId()).findList()).hasSize(0); + assertThat(DB.find(Exam.class).where().eq("parent.id", exam.getId()).findList()).hasSize(0); } @Test @@ -384,7 +378,7 @@ public void testCreateSeveralStudentExamsFails() throws Exception { assertThat(result.status()).isEqualTo(Helpers.FORBIDDEN); // Verify that no student exam was created - assertThat(Ebean.find(Exam.class).where().eq("parent.id", exam.getId()).findList()).hasSize(1); + assertThat(DB.find(Exam.class).where().eq("parent.id", exam.getId()).findList()).hasSize(1); } @Test @@ -405,9 +399,9 @@ public void testCreateStudentExamAlreadyStarted() throws Exception { // Verify that the previous exam was returned, and participation & enrolment still point to it assertThat(studentExam.getId()).isEqualTo(anotherStudentExam.getId()); - assertThat(Ebean.find(ExamEnrolment.class, enrolment.getId()).getExam().getHash()) + assertThat(DB.find(ExamEnrolment.class, enrolment.getId()).getExam().getHash()) .isEqualTo(studentExam.getHash()); - ExamParticipation participation = Ebean + ExamParticipation participation = DB .find(ExamParticipation.class) .where() .eq("exam.id", studentExam.getId()) @@ -420,7 +414,7 @@ public void testCreateStudentExamAlreadyStarted() throws Exception { @RunAsStudent public void testClaimChoiceQuestionOptionOrderAndAnswerSkip() throws Exception { Exam studentExam = prepareExamination(); - ExamSectionQuestion question = Ebean + ExamSectionQuestion question = DB .find(ExamSectionQuestion.class) .where() .eq("examSection.exam", studentExam) diff --git a/test/controllers/QuestionControllerTest.java b/test/controllers/QuestionControllerTest.java index 07ab43f457..45ec65054e 100644 --- a/test/controllers/QuestionControllerTest.java +++ b/test/controllers/QuestionControllerTest.java @@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -22,6 +22,7 @@ import models.sections.ExamSection; import models.sections.ExamSectionQuestion; import models.sections.ExamSectionQuestionOption; +import org.junit.Before; import org.junit.Test; import play.libs.Json; import play.mvc.Result; @@ -29,6 +30,25 @@ public class QuestionControllerTest extends IntegrationTestCase { + private Question question = null; + + @Before + public void setUp() throws Exception { + super.setUp(); + Question question = DB + .find(Question.class) + .findList() + .stream() + .filter(q -> q.getQuestion().contains("Kumpi vai kampi")) + .filter(q -> q.getType() == Question.Type.WeightedMultipleChoiceQuestion) + .findFirst() + .get(); + assertThat(question.getOptions().size()).isEqualTo(3); + question.getQuestionOwners().add(DB.find(User.class, userId)); + question.update(); + this.question = question; + } + @Test @RunAsTeacher public void testAddEssayQuestionToExam() { @@ -36,7 +56,7 @@ public void testAddEssayQuestionToExam() { long examId = 1L; long sectionId = 1L; - ExamSection section = Ebean.find(ExamSection.class, sectionId); + ExamSection section = DB.find(ExamSection.class, sectionId); assert section != null; int sectionQuestionCount = section.getSectionQuestions().size(); @@ -81,16 +101,14 @@ public void testAddEssayQuestionToExam() { assertThat(deserialized.getSectionQuestions().size()).isEqualTo(sectionQuestionCount + 1); // Check that section now has a reference to the original question - assertThat(Ebean.find(ExamSectionQuestion.class).where().eq("question.id", question.getId()).findOne()) + assertThat(DB.find(ExamSectionQuestion.class).where().eq("question.id", question.getId()).findOne()) .isNotNull(); } @Test @RunAsTeacher public void testAddingOptionToWeightedMultipleChoiceQuestion() throws Exception { - Question question = getWeightedMultipleChoiceQuestion(); - - assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); + assertExamSectionQuestion(this.question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); // Add new option to question question = addNewOption(question, 0.75, new Double[] { 1d, 1d, -1d, 0.75d }, -1d); @@ -101,8 +119,6 @@ public void testAddingOptionToWeightedMultipleChoiceQuestion() throws Exception @Test @RunAsTeacher public void testAddingNullScoreOptionToWeightedMultipleChoiceQuestion() throws Exception { - Question question = getWeightedMultipleChoiceQuestion(); - assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); // Add new option to question @@ -114,8 +130,6 @@ public void testAddingNullScoreOptionToWeightedMultipleChoiceQuestion() throws E @Test @RunAsTeacher public void testAddingNegativeOptionToWeightedMultipleChoiceQuestion() throws Exception { - Question question = getWeightedMultipleChoiceQuestion(); - assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); // Add new option to question @@ -127,7 +141,6 @@ public void testAddingNegativeOptionToWeightedMultipleChoiceQuestion() throws Ex @Test @RunAsTeacher public void testDeleteOptionFromWeightedMultipleChoiceQuestion() throws Exception { - Question question = getWeightedMultipleChoiceQuestion(); // Add new option to question and then delete it assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); question = addNewOption(question, 0.75, new Double[] { 1d, 1d, -1d, 0.75d }, -1d); @@ -135,7 +148,7 @@ public void testDeleteOptionFromWeightedMultipleChoiceQuestion() throws Exceptio deleteAddedOption(question); - question = Ebean.find(Question.class, question.getId()); + question = DB.find(Question.class, question.getId()); assert question != null; assertThat(question.getOptions().size()).isEqualTo(3); assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); @@ -144,7 +157,6 @@ public void testDeleteOptionFromWeightedMultipleChoiceQuestion() throws Exceptio @Test @RunAsTeacher public void testDeleteNegativeOptionFromWeightedMultipleChoiceQuestion() throws Exception { - Question question = getWeightedMultipleChoiceQuestion(); // Add new option to question and then delete it assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); question = addNewOption(question, -0.5, new Double[] { 1d, 1d, -1d, -0.5d }, -1.5d); @@ -152,7 +164,7 @@ public void testDeleteNegativeOptionFromWeightedMultipleChoiceQuestion() throws deleteAddedOption(question); - question = Ebean.find(Question.class, question.getId()); + question = DB.find(Question.class, question.getId()); assert question != null; assertThat(question.getOptions().size()).isEqualTo(3); assertExamSectionQuestion(question, 3, 4d, new Double[] { 2d, 2d, -2d }, -2d); @@ -212,7 +224,7 @@ private Question addNewOption( .getOptions() .stream() .sorted(MultipleChoiceOption::compareTo) - .collect(Collectors.toList()); + .toList(); JsonNode json = Json .newObject() .put("id", question.getId()) @@ -249,7 +261,7 @@ private Question addNewOption( Result result = request(Helpers.PUT, "/app/questions/" + question.getId(), json); assertThat(result.status()).isEqualTo(200); - Question saved = Ebean.find(Question.class, question.getId()); + Question saved = DB.find(Question.class, question.getId()); assertThat(saved).isNotNull(); assertThat(saved.getOptions().size()).isEqualTo(4); assertThat(saved.getMinDefaultScore()).isEqualTo(minDefaultScore); @@ -265,22 +277,6 @@ private Question addNewOption( return saved; } - @NotNull - private Question getWeightedMultipleChoiceQuestion() { - Question question = Ebean - .find(Question.class) - .findList() - .stream() - .filter(q -> q.getQuestion().contains("Kumpi vai kampi")) - .filter(q -> q.getType() == Question.Type.WeightedMultipleChoiceQuestion) - .findFirst() - .get(); - assertThat(question.getOptions().size()).isEqualTo(3); - question.getQuestionOwners().add(Ebean.find(User.class, userId)); - question.update(); - return question; - } - private void assertExamSectionQuestion( Question question, int optionSize, @@ -310,12 +306,7 @@ private void assertExamSectionQuestion( @Test @RunAsTeacher public void testExportQuestionToMoodle() { - List ids = Ebean - .find(Question.class) - .findList() - .stream() - .map(Question::getId) - .collect(Collectors.toList()); + List ids = DB.find(Question.class).findList().stream().map(Question::getId).collect(Collectors.toList()); ArrayNode an = Json.newArray(); ids.forEach(an::add); JsonNode params = Json.newObject().set("params", Json.newObject().set("ids", an)); @@ -349,29 +340,26 @@ public void testClaimChoiceQuestionCreateAndUpdate() { boolean hasCorrectAnswer = saved .getOptions() .stream() - .anyMatch( - o -> - o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.CorrectOption && - o.getOption().equals("Oikea") && - o.getDefaultScore() == 1 + .anyMatch(o -> + o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.CorrectOption && + o.getOption().equals("Oikea") && + o.getDefaultScore() == 1 ); boolean hasIncorrectAnswer = saved .getOptions() .stream() - .anyMatch( - o -> - o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.IncorrectOption && - o.getOption().equals("Väärä") && - o.getDefaultScore() == -1 + .anyMatch(o -> + o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.IncorrectOption && + o.getOption().equals("Väärä") && + o.getDefaultScore() == -1 ); boolean hasSkipAnswer = saved .getOptions() .stream() - .anyMatch( - o -> - o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.SkipOption && - o.getOption().equals("EOS") && - o.getDefaultScore() == 0 + .anyMatch(o -> + o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.SkipOption && + o.getOption().equals("EOS") && + o.getDefaultScore() == 0 ); boolean hasRequiredOptions = (hasCorrectAnswer && hasIncorrectAnswer && hasSkipAnswer); @@ -399,11 +387,10 @@ public void testClaimChoiceQuestionCreateAndUpdate() { boolean hasModifiedOption = updated .getOptions() .stream() - .anyMatch( - o -> - o.getOption().equals("Oikea, muokattu") && - o.getDefaultScore() == 2 && - o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.CorrectOption + .anyMatch(o -> + o.getOption().equals("Oikea, muokattu") && + o.getDefaultScore() == 2 && + o.getClaimChoiceType() == MultipleChoiceOption.ClaimChoiceOptionType.CorrectOption ); assertThat(hasModifiedOption).isTrue(); @@ -454,8 +441,7 @@ public void testClaimChoiceOptionValidation() { Question parseQuestionFromResponse(Result res) { JsonNode node = Json.parse(contentAsString(res)); Question question = deserialize(Question.class, node); - Question saved = Ebean.find(Question.class, question.getId()); - return saved; + return DB.find(Question.class, question.getId()); } JsonNode createClaimChoiceOptionJson(String option, Double score, boolean correct, String type) { diff --git a/test/controllers/ReservationInterfaceTest.java b/test/controllers/ReservationInterfaceTest.java index 018ecedfb2..6e901be713 100644 --- a/test/controllers/ReservationInterfaceTest.java +++ b/test/controllers/ReservationInterfaceTest.java @@ -6,7 +6,7 @@ import base.IntegrationTestCase; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import io.ebean.Ebean; +import io.ebean.DB; import models.ExamRoom; import models.calendar.ExceptionWorkingHours; import org.joda.time.DateTime; @@ -46,7 +46,7 @@ public void testGetRooms() { @Test public void getRoomOpeningHours() { - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); ExceptionWorkingHours ewh = new ExceptionWorkingHours(); ewh.setStartDate(DateTime.now().withDayOfMonth(15).toDate()); ewh.setEndDate(DateTime.now().plusMonths(1).withDayOfMonth(15).toDate()); diff --git a/test/controllers/ReviewControllerTest.java b/test/controllers/ReviewControllerTest.java index 49202792ed..232d6591aa 100644 --- a/test/controllers/ReviewControllerTest.java +++ b/test/controllers/ReviewControllerTest.java @@ -24,24 +24,39 @@ import base.RunAsTeacher; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import io.ebean.Ebean; +import io.ebean.DB; import models.Exam; import models.ExamInspection; import models.User; +import org.junit.Before; import org.junit.Test; import play.libs.Json; import play.mvc.Result; public class ReviewControllerTest extends IntegrationTestCase { + private Exam parentExam = null; + + @Before + public void setUp() throws Exception { + super.setUp(); + final User user = DB.find(User.class, userId); + final Exam parent = DB.find(Exam.class).where().eq("name", "Algoritmit, 2013").isNull("parent").findOne(); + assert parent != null; + final ExamInspection examInspection = new ExamInspection(); + examInspection.setUser(user); + examInspection.setExam(parent.getChildren().get(0)); + examInspection.save(); + parent.getExamInspections().add(examInspection); + parent.save(); + this.parentExam = parent; + } + @Test @RunAsTeacher public void getExamReviews() { - final User user = Ebean.find(User.class, userId); - final Exam parent = setUpReviews(user); - // Execute - Result result = get("/app/reviews/" + parent.getId()); + Result result = get("/app/reviews/" + parentExam.getId()); // Verify assertThat(result.status()).isEqualTo(200); @@ -64,11 +79,8 @@ public void getExamReviews() { @Test @RunAsAdmin public void getExamReviewsAsAdmin() { - final User user = Ebean.find(User.class, 3L); - final Exam parent = setUpReviews(user); - // Execute - Result result = get("/app/reviews/" + parent.getId()); + Result result = get("/app/reviews/" + parentExam.getId()); // Verify assertThat(result.status()).isEqualTo(200); @@ -76,23 +88,4 @@ public void getExamReviewsAsAdmin() { ArrayNode participationArray = (ArrayNode) node; assertThat(participationArray.size()).isEqualTo(1); } - - private Exam setUpReviews(User user) { - final Exam parent = Ebean - .find(Exam.class) - .where() - .and() - .eq("name", "Algoritmit, 2013") - .eq("parent", null) - .endAnd() - .findOne(); - assert parent != null; - final ExamInspection examInspection = new ExamInspection(); - examInspection.setUser(user); - examInspection.setExam(parent.getChildren().get(0)); - examInspection.save(); - parent.getExamInspections().add(examInspection); - parent.save(); - return parent; - } } diff --git a/test/controllers/RoomControllerTest.java b/test/controllers/RoomControllerTest.java index f6e101a15d..c5d18158d6 100644 --- a/test/controllers/RoomControllerTest.java +++ b/test/controllers/RoomControllerTest.java @@ -7,7 +7,7 @@ import base.RunAsAdmin; import base.RunAsStudent; import com.fasterxml.jackson.databind.JsonNode; -import io.ebean.Ebean; +import io.ebean.DB; import models.ExamRoom; import org.junit.Test; import play.libs.Json; @@ -20,7 +20,7 @@ public class RoomControllerTest extends IntegrationTestCase { @RunAsAdmin public void testDisableRoom() throws Exception { // Setup - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); assertThat(room.getState()).isNotEqualTo(ExamRoom.State.INACTIVE.toString()); // Execute @@ -32,7 +32,7 @@ public void testDisableRoom() throws Exception { ExamRoom deserialized = deserialize(ExamRoom.class, node); assertThat(deserialized.getState()).isEqualTo(ExamRoom.State.INACTIVE.toString()); - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); assertThat(room.getState()).isEqualTo(ExamRoom.State.INACTIVE.toString()); } @@ -40,7 +40,7 @@ public void testDisableRoom() throws Exception { @RunAsStudent public void testDisabledRoomNotVisibleToStudent() throws Exception { // Setup - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); room.setState(ExamRoom.State.INACTIVE.toString()); room.update(); @@ -57,7 +57,7 @@ public void testDisabledRoomNotVisibleToStudent() throws Exception { @RunAsAdmin public void testEnableRoom() throws Exception { // Setup - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); room.setState(ExamRoom.State.INACTIVE.toString()); room.update(); @@ -70,7 +70,7 @@ public void testEnableRoom() throws Exception { ExamRoom deserialized = deserialize(ExamRoom.class, node); assertThat(deserialized.getState()).isEqualTo(ExamRoom.State.ACTIVE.toString()); - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); assertThat(room.getState()).isEqualTo(ExamRoom.State.ACTIVE.toString()); } @@ -78,7 +78,7 @@ public void testEnableRoom() throws Exception { @RunAsStudent public void testEnabledRoomVisibleToStudent() throws Exception { // Setup - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); room.setState(ExamRoom.State.ACTIVE.toString()); room.update(); diff --git a/test/controllers/SessionControllerTest.java b/test/controllers/SessionControllerTest.java index f0ecb3b6c1..7ca870c029 100644 --- a/test/controllers/SessionControllerTest.java +++ b/test/controllers/SessionControllerTest.java @@ -4,7 +4,7 @@ import base.IntegrationTestCase; import com.google.common.collect.ImmutableMap; -import io.ebean.Ebean; +import io.ebean.DB; import models.Role; import models.User; import org.junit.Test; @@ -14,12 +14,12 @@ public class SessionControllerTest extends IntegrationTestCase { @Test public void testLoginAsNewUser() { String eppn = "newuser@test.org"; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login(eppn); - user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNotNull(); assertThat(user.getRoles()).hasSize(1); assertThat(user.getOrganisation()).isNotNull(); @@ -27,12 +27,13 @@ public void testLoginAsNewUser() { assertThat(user.getFirstName()).isEqualTo("George"); assertThat(user.getLastName()).isEqualTo("Lazenby"); assertThat(user.getUserIdentifier()).isEqualTo("org1.org:11111 org2.org:22222 org3.org:33333"); + assertThat(user.getLanguage().getCode()).isEqualTo("en"); // was de originally, but not supported } @Test public void testLoginWithDuplicateUserIdentifierKeys() { String eppn = "newuser@test.org"; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login( @@ -46,7 +47,7 @@ public void testLoginWithDuplicateUserIdentifierKeys() { ) ); - user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNotNull(); assertThat(user.getUserIdentifier()).isEqualTo("org1.org:null org2.org:aaaaa"); } @@ -54,7 +55,7 @@ public void testLoginWithDuplicateUserIdentifierKeys() { @Test public void testLoginWithOtherIdentifierKeys() { String eppn = "newuser@test.org"; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login( @@ -67,7 +68,7 @@ public void testLoginWithOtherIdentifierKeys() { ) ); - user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNotNull(); assertThat(user.getUserIdentifier()).isEqualTo("org2.org:aaaaa"); } @@ -75,12 +76,12 @@ public void testLoginWithOtherIdentifierKeys() { @Test public void testLoginWithInvalidUserIdentifierString() { String eppn = "newuser@test.org"; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login(eppn, ImmutableMap.of("schacPersonalUniqueCode", "11111")); - user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNotNull(); assertThat(user.getUserIdentifier()).isEqualTo("11111"); } @@ -88,12 +89,12 @@ public void testLoginWithInvalidUserIdentifierString() { @Test public void testLoginWithMissingUserIdentifierValue() { String eppn = "newuser@test.org"; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login(eppn, ImmutableMap.of("schacPersonalUniqueCode", "urn:schac:personalUniqueCode:int:studentID:org2.org:")); - user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNotNull(); assertThat(user.getUserIdentifier()).isEqualTo("org2.org:null"); } @@ -101,7 +102,7 @@ public void testLoginWithMissingUserIdentifierValue() { @Test public void testLoginWithNationalUserIdentifier() { String eppn = "newuser@test.org"; - User user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNull(); login( @@ -113,7 +114,7 @@ public void testLoginWithNationalUserIdentifier() { ) ); - user = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + user = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(user).isNotNull(); assertThat(user.getUserIdentifier()).isEqualTo("org2.org:111"); } diff --git a/test/controllers/StudentActionControllerTest.java b/test/controllers/StudentActionControllerTest.java index ea2e1385a8..f93ca5455f 100644 --- a/test/controllers/StudentActionControllerTest.java +++ b/test/controllers/StudentActionControllerTest.java @@ -7,7 +7,7 @@ import base.RunAsStudent; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.TimeZone; import java.util.stream.StreamSupport; import models.Exam; @@ -29,12 +29,12 @@ public class StudentActionControllerTest extends IntegrationTestCase { @Before public void setUp() throws Exception { super.setUp(); - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); } @Test @RunAsStudent - public void testGetEnrolmentsForUserWithExternalReservation() throws Exception { + public void testGetEnrolmentsForUserWithExternalReservation() { createEnrolment(1L); ExamEnrolment enrolment = createEnrolment(2L); final Reservation reservation = enrolment.getReservation(); @@ -69,13 +69,13 @@ public void testGetEnrolmentsForUserWithExternalReservation() throws Exception { } private ExamEnrolment createEnrolment(long examId) { - Exam exam = Ebean.find(Exam.class).where().idEq(examId).findOne(); - exam.setExamActiveEndDate(DateTime.now().plusYears(1)); + Exam exam = DB.find(Exam.class).where().idEq(examId).findOne(); + exam.setPeriodEnd(DateTime.now().plusYears(1)); exam.setState(Exam.State.PUBLISHED); exam.save(); - User user = Ebean.find(User.class, userId); - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + User user = DB.find(User.class, userId); + ExamRoom room = DB.find(ExamRoom.class, 1L); ExamMachine machine = room.getExamMachines().get(0); machine.setIpAddress("127.0.0.1"); // so that the IP check won't fail machine.update(); diff --git a/test/controllers/integration/ExamAPIControllerTest.java b/test/controllers/integration/ExamAPIControllerTest.java index aace2f2bef..bfae2e7c94 100644 --- a/test/controllers/integration/ExamAPIControllerTest.java +++ b/test/controllers/integration/ExamAPIControllerTest.java @@ -22,7 +22,7 @@ import base.IntegrationTestCase; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import io.ebean.Ebean; +import io.ebean.DB; import java.util.List; import java.util.Optional; import models.Exam; @@ -44,36 +44,34 @@ public class ExamAPIControllerTest extends IntegrationTestCase { @Before public void setUp() throws Exception { super.setUp(); - final List types = Ebean.find(ExamExecutionType.class).findList(); + final List types = DB.find(ExamExecutionType.class).findList(); publicType = findType(types, ExamExecutionType.Type.PUBLIC).orElse(null); privateType = findType(types, ExamExecutionType.Type.PRIVATE).orElse(null); final LocalDateTime startDate = LocalDateTime.now().plusDays(1); final LocalDateTime endDate = LocalDateTime.now().plusDays(10); - exams = Ebean.find(Exam.class).findList(); + exams = DB.find(Exam.class).findList(); // Set all exams to start on future - exams.forEach( - e -> { - e.setState(Exam.State.PUBLISHED); - e.setExamActiveStartDate(startDate.toDateTime()); - e.setExamActiveEndDate(endDate.toDateTime()); - e.setExecutionType(publicType); - e.save(); - } - ); + exams.forEach(e -> { + e.setState(Exam.State.PUBLISHED); + e.setPeriodStart(startDate.toDateTime()); + e.setPeriodEnd(endDate.toDateTime()); + e.setExecutionType(publicType); + e.save(); + }); } @Test public void testGetActiveExams() { // Pick first exam and set it already started but not yet ended (included) final Exam first = exams.get(0); - first.setExamActiveStartDate(LocalDateTime.now().minusDays(1).toDateTime()); + first.setPeriodStart(LocalDateTime.now().minusDays(1).toDateTime()); first.save(); // Set second exam already ended (excluded) final Exam second = exams.get(1); - second.setExamActiveStartDate(LocalDateTime.now().minusDays(2).toDateTime()); - second.setExamActiveEndDate(LocalDateTime.now().minusDays(1).toDateTime()); + second.setPeriodStart(LocalDateTime.now().minusDays(2).toDateTime()); + second.setPeriodEnd(LocalDateTime.now().minusDays(1).toDateTime()); second.save(); // Set third exam as private (excluded) @@ -96,8 +94,8 @@ public void testGetActiveExams() { assertThat(records).hasSize(exams.size() - 3); records .elements() - .forEachRemaining( - n -> assertThat(n.get("id").asLong()).isNotIn(second.getId(), third.getId(), fourth.getId()) + .forEachRemaining(n -> + assertThat(n.get("id").asLong()).isNotIn(second.getId(), third.getId(), fourth.getId()) ); String filter = DateTime.now().minusDays(3).toString("yyyy-MM-dd"); diff --git a/test/controllers/integration/ExternalCourseHandlerTest.java b/test/controllers/integration/ExternalCourseHandlerTest.java index efd7094261..e4b4c1c9bf 100644 --- a/test/controllers/integration/ExternalCourseHandlerTest.java +++ b/test/controllers/integration/ExternalCourseHandlerTest.java @@ -8,7 +8,7 @@ import base.RunAsStudent; import base.RunAsTeacher; import com.fasterxml.jackson.databind.JsonNode; -import io.ebean.Ebean; +import io.ebean.DB; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -71,10 +71,10 @@ public static void startServer() throws Exception { } private void setUserOrg(String code) { - User user = Ebean.find(User.class).where().eq("eppn", "student@funet.fi").findOne(); + User user = DB.find(User.class).where().eq("eppn", "student@funet.fi").findOne(); Organisation org = null; if (code != null) { - org = Ebean.find(Organisation.class).where().eq("code", code).findOne(); + org = DB.find(Organisation.class).where().eq("code", code).findOne(); } user.setOrganisation(org); user.update(); @@ -95,7 +95,7 @@ public void testGetCourseDefaultOrganisation() { assertThat(course.getGradeScale().getDisplayName()).isEqualTo("0-5"); assertThat(course.getGradeScale().getExternalRef()).isEqualTo("9"); assertThat(course.getCreditsLanguage()).isEqualTo("fi"); - List grades = Ebean + List grades = DB .find(Grade.class) .where() .eq("gradeScale.id", course.getGradeScale().getId()) @@ -103,7 +103,7 @@ public void testGetCourseDefaultOrganisation() { assertThat(grades).hasSize(7); assertThat(grades.stream().filter(Grade::getMarksRejection).collect(Collectors.toList())).hasSize(1); // Check that the imported course got into db - assertThat(Ebean.find(Course.class).where().eq("code", "2121219_abcdefghijklmnop").findOne()).isNotNull(); + assertThat(DB.find(Course.class).where().eq("code", "2121219_abcdefghijklmnop").findOne()).isNotNull(); } @Test @@ -122,7 +122,7 @@ public void testGetCourseDefaultOrganisation2() { assertThat(course.getGradeScale().getDisplayName()).isEqualTo("0-5"); assertThat(course.getGradeScale().getExternalRef()).isEqualTo("sis-0-5"); assertThat(course.getCreditsLanguage()).isEqualTo("en"); - List grades = Ebean + List grades = DB .find(Grade.class) .where() .eq("gradeScale.id", course.getGradeScale().getId()) @@ -130,7 +130,7 @@ public void testGetCourseDefaultOrganisation2() { assertThat(grades).hasSize(6); assertThat(grades.stream().filter(Grade::getMarksRejection).collect(Collectors.toList())).hasSize(1); // Check that the imported course got into db - Course c = Ebean.find(Course.class).where().eq("code", "MAT21014_hy-CUR-138798147").findOne(); + Course c = DB.find(Course.class).where().eq("code", "MAT21014_hy-CUR-138798147").findOne(); assertThat(c).isNotNull(); assertThat(c.getGradeScale().getGrades()).hasSize(6); } @@ -149,7 +149,7 @@ public void testUpdateCourse() { Result result = get("/app/courses?filter=code&q=2121219"); assertThat(result.status()).isEqualTo(200); - Course course = Ebean.find(Course.class).where().eq("code", "2121219_abcdefghijklmnop").findOne(); + Course course = DB.find(Course.class).where().eq("code", "2121219_abcdefghijklmnop").findOne(); assertThat(course).isNotNull(); assertThat(course.getName()).endsWith("2"); assertThat(course.getGradeScale().getDisplayName()).isEqualTo("1-2"); @@ -178,7 +178,7 @@ public void testAlwaysSearchForRemoteCourse() { Course c2 = deserialize(Course.class, node.get(1)); assertThat(c2.getCode()).isEqualTo("2121219_abcdefghijklmnopq"); // check that remote course was added to database - assertThat(Ebean.find(Course.class).where().eq("code", "2121219_abcdefghijklmnop")).isNotNull(); + assertThat(DB.find(Course.class).where().eq("code", "2121219_abcdefghijklmnop")).isNotNull(); } @Test @@ -196,7 +196,7 @@ public void testGetCourseOfAnotherOrganisation() { assertThat(course.getGradeScale().getType()).isEqualTo(GradeScale.Type.OTHER); assertThat(course.getGradeScale().getDisplayName()).isEqualTo("0-5"); assertThat(course.getGradeScale().getExternalRef()).isEqualTo("9"); - List grades = Ebean + List grades = DB .find(Grade.class) .where() .eq("gradeScale.id", course.getGradeScale().getId()) diff --git a/test/controllers/iop/BaseCollaborativeAttachmentControllerTest.java b/test/controllers/iop/BaseCollaborativeAttachmentControllerTest.java index dbddac5843..dbd5398909 100644 --- a/test/controllers/iop/BaseCollaborativeAttachmentControllerTest.java +++ b/test/controllers/iop/BaseCollaborativeAttachmentControllerTest.java @@ -18,13 +18,11 @@ import static org.fest.assertions.Assertions.assertThat; -import akka.actor.ActorSystem; -import akka.stream.Materializer; import base.IntegrationTestCase; import helpers.AttachmentServlet; import helpers.ExamServlet; import helpers.RemoteServerHelper; -import io.ebean.Ebean; +import io.ebean.DB; import jakarta.servlet.MultipartConfigElement; import java.io.File; import java.io.IOException; @@ -39,6 +37,8 @@ import models.sections.ExamSectionQuestion; import net.jodah.concurrentunit.Waiter; import org.apache.commons.io.FileUtils; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.stream.Materializer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -91,9 +91,9 @@ public static void shutdownServer() throws Exception { @Before public void setUp() throws Exception { super.setUp(); - exam = Ebean.find(Exam.class, 1L); + exam = DB.find(Exam.class, 1L); assert exam != null; - exam.setExecutionType(Ebean.find(ExamExecutionType.class, 1L)); + exam.setExecutionType(DB.find(ExamExecutionType.class, 1L)); exam.setExternal(true); final Attachment examAttachment = createAttachment("test_image.png", testImage.getAbsolutePath(), "image/png"); examAttachment.setExternalId("ab123fcdgkk"); diff --git a/test/controllers/iop/CollaborativeAttachmentControllerTest.java b/test/controllers/iop/CollaborativeAttachmentControllerTest.java index 2813fcab87..85845929c1 100644 --- a/test/controllers/iop/CollaborativeAttachmentControllerTest.java +++ b/test/controllers/iop/CollaborativeAttachmentControllerTest.java @@ -18,10 +18,6 @@ import static org.fest.assertions.Assertions.assertThat; -import akka.stream.Materializer; -import akka.stream.javadsl.FileIO; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import base.RunAsStudent; import base.RunAsTeacher; import com.fasterxml.jackson.databind.JsonNode; @@ -36,6 +32,10 @@ import models.json.CollaborativeExam; import models.questions.EssayAnswer; import models.sections.ExamSectionQuestion; +import org.apache.pekko.stream.Materializer; +import org.apache.pekko.stream.javadsl.FileIO; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; import org.junit.Test; import play.libs.Json; import play.mvc.Http; diff --git a/test/controllers/iop/DataTransferControllerTest.java b/test/controllers/iop/DataTransferControllerTest.java index a88f7b84f3..82988378c3 100644 --- a/test/controllers/iop/DataTransferControllerTest.java +++ b/test/controllers/iop/DataTransferControllerTest.java @@ -9,7 +9,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import helpers.RemoteServerHelper; -import io.ebean.Ebean; +import io.ebean.DB; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -95,7 +95,7 @@ public static void shutdownServer() throws Exception { @RunAsTeacher public void testExportQuestion() { User user = getLoggerUser(); - List questions = Ebean + List questions = DB .find(Question.class) .where() .or() @@ -115,7 +115,7 @@ public void testExportQuestion() { @RunAsTeacher public void testExportQuestionWithAttachment() throws InterruptedException, TimeoutException { User user = getLoggerUser(); - Question question = Ebean + Question question = DB .find(Question.class) .where() .or() @@ -144,12 +144,12 @@ public void testImportQuestion() throws IOException { Result result = request(Helpers.POST, "/integration/iop/import", json); assertThat(result.status()).isEqualTo(201); - assertThat(Ebean.find(Question.class).where().like("question", "% **import").findCount()).isEqualTo(22); + assertThat(DB.find(Question.class).where().like("question", "% **import").findCount()).isEqualTo(22); } @Test public void testImportQuestionWithTags() throws IOException { - User user = Ebean.find(User.class).where().eq("email", "teacher@funet.fi").findOne(); + User user = DB.find(User.class).where().eq("email", "teacher@funet.fi").findOne(); Tag existing = new Tag(); existing.setCreatorWithDate(user); existing.setModifierWithDate(user); @@ -162,7 +162,7 @@ public void testImportQuestionWithTags() throws IOException { Result result = request(Helpers.POST, "/integration/iop/import", json); assertThat(result.status()).isEqualTo(201); assertThat( - (long) Ebean.find(Question.class).where().like("question", "% **import").findOne().getTags().size() == 2 + (long) DB.find(Question.class).where().like("question", "% **import").findOne().getTags().size() == 2 ); } @@ -175,7 +175,7 @@ public void testImportQuestionWithAttachment() throws IOException { Result result = request(Helpers.POST, "/integration/iop/import", json); assertThat(result.status()).isEqualTo(201); - Question question = Ebean.find(Question.class).where().like("question", "% **import").findOne(); + Question question = DB.find(Question.class).where().like("question", "% **import").findOne(); assertThat(question.getAttachment()).isNotNull(); } } diff --git a/test/controllers/iop/ExternalAttachmentControllerTest.java b/test/controllers/iop/ExternalAttachmentControllerTest.java index 21e85a1c88..575c7be77e 100644 --- a/test/controllers/iop/ExternalAttachmentControllerTest.java +++ b/test/controllers/iop/ExternalAttachmentControllerTest.java @@ -18,14 +18,10 @@ import static org.fest.assertions.Assertions.assertThat; -import akka.stream.Materializer; -import akka.stream.javadsl.FileIO; -import akka.stream.javadsl.Source; -import akka.util.ByteString; import base.RunAsStudent; import base.RunAsTeacher; import com.fasterxml.jackson.databind.JsonNode; -import io.ebean.Ebean; +import io.ebean.DB; import java.io.IOException; import java.util.Arrays; import javax.validation.constraints.NotNull; @@ -34,6 +30,10 @@ import models.json.ExternalExam; import models.questions.EssayAnswer; import models.sections.ExamSectionQuestion; +import org.apache.pekko.stream.Materializer; +import org.apache.pekko.stream.javadsl.FileIO; +import org.apache.pekko.stream.javadsl.Source; +import org.apache.pekko.util.ByteString; import org.junit.Test; import play.libs.Json; import play.mvc.Http; @@ -112,7 +112,7 @@ public void testAddAttachmentToQuestionAnswer() throws Exception { assertThat(attachmentJson.get("externalId").asText()).isEqualTo("abcdefg123456"); assertThat(attachmentJson.get("fileName").asText()).isEqualTo("test_image.png"); - Ebean.refresh(externalExam); + DB.refresh(externalExam); final Exam e = externalExam.deserialize(); final ExamSectionQuestion sq = getExamSectionQuestion(e, examSectionQuestion.getId()); assertThat(sq.getEssayAnswer()).isNotNull(); @@ -141,7 +141,7 @@ public void testDeleteQuestionAnswerAttachment() throws Exception { assertThat(result.status()).isEqualTo(200); assertLastCall(Helpers.DELETE); - Ebean.refresh(externalExam); + DB.refresh(externalExam); final Exam e = externalExam.deserialize(); final ExamSectionQuestion sq = getExamSectionQuestion(e, examSectionQuestion.getId()); assertThat(sq.getEssayAnswer()).isNotNull(); diff --git a/test/controllers/iop/ExternalCalendarInterfaceTest.java b/test/controllers/iop/ExternalCalendarInterfaceTest.java index 7312e563ab..b6b8888105 100644 --- a/test/controllers/iop/ExternalCalendarInterfaceTest.java +++ b/test/controllers/iop/ExternalCalendarInterfaceTest.java @@ -16,7 +16,8 @@ import com.icegreen.greenmail.util.ServerSetupTest; import helpers.AttachmentServlet; import helpers.RemoteServerHelper; -import io.ebean.Ebean; +import io.ebean.DB; +import jakarta.mail.internet.MimeMessage; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; @@ -28,7 +29,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import javax.mail.internet.MimeMessage; import models.AutoEvaluationConfig; import models.Exam; import models.ExamEnrolment; @@ -155,7 +155,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { @Override protected Application provideApplication() { - Map config = Map.of("sitnet.integration.enrolmentPermissionCheck.active", false); + Map config = Map.of("exam.integration.enrolmentPermissionCheck.active", false); return new GuiceApplicationBuilder().configure(config).build(); } @@ -186,29 +186,23 @@ public static void startServer() throws Exception { } private void initialize(User other) { - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); exam = - Ebean - .find(Exam.class) - .fetch("examSections") - .fetch("examSections.sectionQuestions") - .where() - .idEq(1L) - .findOne(); + DB.find(Exam.class).fetch("examSections").fetch("examSections.sectionQuestions").where().idEq(1L).findOne(); initExamSectionQuestions(exam); - exam.setExamActiveStartDate(DateTime.now().minusDays(1)); - exam.setExamActiveEndDate(DateTime.now().plusDays(1)); + exam.setPeriodStart(DateTime.now().minusDays(1)); + exam.setPeriodEnd(DateTime.now().plusDays(1)); exam.update(); Long id = other == null ? userId : other.getId(); if (id != null) { - user = Ebean.find(User.class, id); - user.setLanguage(Ebean.find(Language.class, "en")); + user = DB.find(User.class, id); + user.setLanguage(DB.find(Language.class, "en")); user.update(); } - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.getExamMachines().get(0).setIpAddress("127.0.0.1"); room.getExamMachines().get(0).update(); @@ -255,7 +249,7 @@ public void testGetSlots() { public void testGetSlotsWithConflictingReservation() { // Setup a conflicting reservation initialize(null); - Exam exam2 = Ebean.find(Exam.class).where().eq("state", Exam.State.PUBLISHED).findList().get(1); + Exam exam2 = DB.find(Exam.class).where().eq("state", Exam.State.PUBLISHED).findList().get(1); Reservation reservation = new Reservation(); reservation.setUser(user); reservation.setStartAt(DateTime.now().plusMinutes(90)); @@ -290,7 +284,7 @@ public void testGetSlotsWithConflictingReservation() { @Test public void testProvideSlots() { - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.update(); int machineCount = room @@ -328,7 +322,7 @@ public void testProvideSlots() { @Test public void testProvideReservation() { - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.update(); @@ -347,7 +341,7 @@ public void testProvideReservation() { .put("user", "studentone@uni.org") ); assertThat(result.status()).isEqualTo(201); - Reservation reservation = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + Reservation reservation = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); assertThat(reservation).isNotNull(); assertThat(reservation.getMachine().getRoom().getExternalRef()).isEqualTo(ROOM_REF); assertThat(reservation.getStartAt()).isEqualTo(start); @@ -356,7 +350,7 @@ public void testProvideReservation() { @Test public void testAcknowledgeReservationRemoval() { - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.update(); @@ -369,7 +363,7 @@ public void testAcknowledgeReservationRemoval() { Result result = request(Helpers.DELETE, "/integration/iop/reservations/" + RESERVATION_REF, null); assertThat(result.status()).isEqualTo(200); - Reservation removed = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + Reservation removed = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); assertThat(removed).isNull(); } @@ -396,9 +390,9 @@ public void testAcknowledgeReservationRevocation() { Result result = request(Helpers.DELETE, "/integration/iop/reservations/" + RESERVATION_REF + "/force", null); assertThat(result.status()).isEqualTo(200); - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNull(); - assertThat(Ebean.find(Reservation.class, reservation.getId())).isNull(); + assertThat(DB.find(Reservation.class, reservation.getId())).isNull(); } @Test @@ -424,14 +418,14 @@ public void testAcknowledgeReservationRevocationInEffectFails() { Result result = request(Helpers.DELETE, "/integration/iop/reservations/" + RESERVATION_REF + "/force", null); assertThat(result.status()).isEqualTo(403); - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNotNull(); } @Test @RunAsAdmin public void testRequestReservationRevocation() { - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.update(); @@ -450,14 +444,14 @@ public void testRequestReservationRevocation() { Json.newObject().put("msg", "msg") ); assertThat(result.status()).isEqualTo(200); - Reservation removed = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + Reservation removed = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); assertThat(removed).isNull(); } @Test @RunAsAdmin public void testDeleteProvidedReservationInProgressFails() { - room = Ebean.find(ExamRoom.class, 1L); + room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.update(); @@ -475,7 +469,7 @@ public void testDeleteProvidedReservationInProgressFails() { Json.newObject().put("msg", "msg") ); assertThat(result.status()).isEqualTo(403); - Reservation removed = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + Reservation removed = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); assertThat(removed).isNotNull(); } @@ -498,7 +492,7 @@ private void setAutoEvaluationConfig() { @Test public void testProvideEnrolment() { - initialize(Ebean.find(User.class, 1)); + initialize(DB.find(User.class, 1)); setAutoEvaluationConfig(); Reservation reservation = new Reservation(); reservation.setExternalRef(RESERVATION_REF); @@ -536,12 +530,12 @@ public void testLoginAsTemporalStudentVisitor() throws Exception { login(eppn); - User newUser = Ebean.find(User.class).where().eq("eppn", eppn).findOne(); + User newUser = DB.find(User.class).where().eq("eppn", eppn).findOne(); assertThat(newUser).isNotNull(); assertThat(newUser.getRoles()).hasSize(1); assertThat(newUser.getRoles().get(0).getName()).isEqualTo(Role.Name.TEACHER.toString()); - reservation = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + reservation = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); assertThat(reservation.getUser().getId()).isEqualTo(newUser.getId()); // See that user is eventually directed to waiting room @@ -553,7 +547,7 @@ public void testLoginAsTemporalStudentVisitor() throws Exception { assertThat(result.status()).isEqualTo(403); // see that enrolment was created for the user - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .eq("reservation.externalRef", RESERVATION_REF) @@ -612,7 +606,7 @@ public void testRequestReservation() throws Exception { JsonNode body = Json.parse(contentAsString(result)); assertThat(body.asText()).isEqualTo(RESERVATION_REF); - Reservation created = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + Reservation created = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); assertThat(created).isNotNull(); assertThat(created.getEnrolment().getOptionalSections()).hasSize(1); ExternalReservation external = created.getExternalReservation(); @@ -648,7 +642,7 @@ public void testRequestReservationAndReEnrollBeforeAssessmentReturned() throws E JsonNode body = Json.parse(contentAsString(result)); assertThat(body.asText()).isEqualTo(RESERVATION_REF); - Reservation created = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); + Reservation created = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF).findOne(); created.setStartAt(DateTime.now().minusHours(2)); created.setEndAt(DateTime.now().minusHours(1)); created.save(); @@ -687,10 +681,10 @@ public void testRequestReservationPreviousInEffect() { Result result = request(Helpers.POST, "/app/iop/reservations/external", json); assertThat(result.status()).isEqualTo(403); - assertThat(contentAsString(result).equals("sitnet_error_enrolment_not_found")); + assertThat(contentAsString(result).equals("i18n_error_enrolment_not_found")); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation().getId()).isEqualTo(reservation.getId()); } @@ -728,12 +722,12 @@ public void testRequestReservationPreviousInTheFuture() { Result result = request(Helpers.POST, "/app/iop/reservations/external", json); assertThat(result.status()).isEqualTo(201); - assertThat(contentAsString(result).equals("sitnet_error_enrolment_not_found")); + assertThat(contentAsString(result).equals("i18n_error_enrolment_not_found")); // Verify - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation().getId()).isNotEqualTo(reservation.getId()); - assertThat(Ebean.find(Reservation.class, reservation.getId())).isNull(); + assertThat(DB.find(Reservation.class, reservation.getId())).isNull(); greenMail.waitForIncomingEmail(5000, 1); } @@ -762,9 +756,9 @@ public void testRequestReservationRemoval() throws Exception { Result result = request(Helpers.DELETE, "/app/iop/reservations/external/" + RESERVATION_REF, null); assertThat(result.status()).isEqualTo(200); - ExamEnrolment ee = Ebean.find(ExamEnrolment.class, enrolment.getId()); + ExamEnrolment ee = DB.find(ExamEnrolment.class, enrolment.getId()); assertThat(ee.getReservation()).isNull(); - assertThat(Ebean.find(Reservation.class, reservation.getId())).isNull(); + assertThat(DB.find(Reservation.class, reservation.getId())).isNull(); // Check that correct mail was sent assertThat(greenMail.waitForIncomingEmail(MAIL_TIMEOUT, 1)).isTrue(); @@ -790,7 +784,7 @@ public void testRequestReservationRemovalAfterRemoteLogin() throws Exception { reservation.save(); login(eppn); - ExamEnrolment enrolment = Ebean + ExamEnrolment enrolment = DB .find(ExamEnrolment.class) .where() .eq("reservation.externalRef", RESERVATION_REF) @@ -800,8 +794,8 @@ public void testRequestReservationRemovalAfterRemoteLogin() throws Exception { Result result = request(Helpers.DELETE, "/integration/iop/reservations/" + RESERVATION_REF, null); assertThat(result.status()).isEqualTo(200); - assertThat(Ebean.find(Reservation.class, reservation.getId())).isNull(); - assertThat(Ebean.find(ExamEnrolment.class, enrolment.getId())).isNull(); - assertThat(Ebean.find(ExternalExam.class, enrolment.getExternalExam().getId())).isNull(); + assertThat(DB.find(Reservation.class, reservation.getId())).isNull(); + assertThat(DB.find(ExamEnrolment.class, enrolment.getId())).isNull(); + assertThat(DB.find(ExternalExam.class, enrolment.getExternalExam().getId())).isNull(); } } diff --git a/test/controllers/iop/ExternalExamControllerTest.java b/test/controllers/iop/ExternalExamControllerTest.java index 78313a0068..e5ef0b5d59 100644 --- a/test/controllers/iop/ExternalExamControllerTest.java +++ b/test/controllers/iop/ExternalExamControllerTest.java @@ -10,7 +10,7 @@ import com.icegreen.greenmail.util.ServerSetupTest; import helpers.AttachmentServlet; import helpers.RemoteServerHelper; -import io.ebean.Ebean; +import io.ebean.DB; import jakarta.servlet.MultipartConfigElement; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServlet; @@ -52,9 +52,7 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; -import play.Application; import play.Logger; -import play.inject.guice.GuiceApplicationBuilder; import play.libs.Json; import play.mvc.Result; import play.test.Helpers; @@ -76,8 +74,6 @@ public class ExternalExamControllerTest extends IntegrationTestCase { private ExamEnrolment enrolment; private final Reservation reservation = new Reservation(); - private final Application app = new GuiceApplicationBuilder().build(); - @Rule public final com.icegreen.greenmail.junit4.GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP) .withConfiguration(new GreenMailConfiguration().withDisabledAuthentication()); @@ -141,8 +137,8 @@ public static void shutdownServer() throws Exception { @Override protected void onBeforeLogin() { - User user = Ebean.find(User.class, userId == null ? 3L : userId); - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + User user = DB.find(User.class, userId == null ? 3L : userId); + ExamRoom room = DB.find(ExamRoom.class, 1L); ExamMachine machine = room.getExamMachines().get(0); machine.setIpAddress("127.0.0.1"); // so that the IP check won't fail machine.update(); @@ -159,26 +155,20 @@ protected void onBeforeLogin() { @Before public void setUp() throws Exception { super.setUp(); - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); exam = - Ebean - .find(Exam.class) - .fetch("examSections") - .fetch("examSections.sectionQuestions") - .where() - .idEq(1L) - .findOne(); + DB.find(Exam.class).fetch("examSections").fetch("examSections.sectionQuestions").where().idEq(1L).findOne(); initExamSectionQuestions(exam); - exam.setExamActiveStartDate(DateTime.now().minusDays(1)); - exam.setExamActiveEndDate(DateTime.now().plusDays(1)); + exam.setPeriodStart(DateTime.now().minusDays(1)); + exam.setPeriodEnd(DateTime.now().plusDays(1)); exam.setHash(HASH); - User owner = Ebean.find(User.class, 2L); + User owner = DB.find(User.class, 2L); exam.getExamOwners().add(owner); exam.update(); - User user = Ebean.find(User.class, 1L); - user.setLanguage(Ebean.find(Language.class, "en")); + User user = DB.find(User.class, 1L); + user.setLanguage(DB.find(Language.class, "en")); user.update(); - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); room.setExternalRef(ROOM_REF); room.getExamMachines().get(0).setIpAddress("127.0.0.1"); room.getExamMachines().get(0).update(); @@ -206,7 +196,7 @@ public void tearDown() { @Test public void testRequestEnrolment() throws Exception { login("student@funet.fi"); - Reservation external = Ebean + Reservation external = DB .find(Reservation.class) .fetch("enrolment") .fetch("enrolment.externalExam") @@ -239,7 +229,7 @@ public void testReceiveExamAttainment() throws Exception { greenMail.purgeEmailFromAllMailboxes(); assertThat(greenMail.waitForIncomingEmail(MAIL_TIMEOUT, 2)).isTrue(); - Exam attainment = Ebean.find(Exam.class).where().eq("parent", exam).findOne(); + Exam attainment = DB.find(Exam.class).where().eq("parent", exam).findOne(); assertThat(attainment).isNotNull(); // Auto-evaluation expected to occur so state should be GRADED assertThat(attainment.getState()).isEqualTo(Exam.State.GRADED); @@ -277,7 +267,7 @@ public void testReceiveNoShow() throws Exception { reservation.setExternalRef(RESERVATION_REF_2); reservation.setStartAt(DateTime.now().minusHours(3)); reservation.setEndAt(DateTime.now().minusHours(2)); - reservation.setUser(Ebean.find(User.class).where().eq("firstName", "Sauli").findOne()); + reservation.setUser(DB.find(User.class).where().eq("firstName", "Sauli").findOne()); //reservation.setMachine(room.getExamMachines().get(0)); ExternalReservation er = new ExternalReservation(); er.setOrgRef("org1"); @@ -298,7 +288,7 @@ public void testReceiveNoShow() throws Exception { ); assertThat(result.status()).isEqualTo(200); - Reservation r = Ebean.find(Reservation.class).where().eq("externalRef", RESERVATION_REF_2).findOne(); + Reservation r = DB.find(Reservation.class).where().eq("externalRef", RESERVATION_REF_2).findOne(); assertThat(r).isNotNull(); assertThat(r.getEnrolment().isNoShow()).isTrue(); } diff --git a/test/controllers/iop/ExternalExaminationControllerTest.java b/test/controllers/iop/ExternalExaminationControllerTest.java index 1fa57b30b0..4f9f80177a 100644 --- a/test/controllers/iop/ExternalExaminationControllerTest.java +++ b/test/controllers/iop/ExternalExaminationControllerTest.java @@ -1,5 +1,8 @@ package controllers.iop; +import static org.fest.assertions.Assertions.assertThat; +import static play.test.Helpers.contentAsString; + import base.IntegrationTestCase; import base.RunAsStudent; import com.fasterxml.jackson.databind.JsonNode; @@ -10,7 +13,7 @@ import com.icegreen.greenmail.configuration.GreenMailConfiguration; import com.icegreen.greenmail.junit4.GreenMailRule; import com.icegreen.greenmail.util.ServerSetupTest; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.text.json.EJson; import java.io.File; import java.io.IOException; @@ -31,14 +34,12 @@ import models.questions.Question; import models.sections.ExamSectionQuestion; import models.sections.ExamSectionQuestionOption; -import static org.fest.assertions.Assertions.assertThat; import org.joda.time.DateTime; import org.junit.Rule; import org.junit.Test; import play.libs.Json; import play.mvc.Result; import play.test.Helpers; -import static play.test.Helpers.contentAsString; import util.json.JsonDeserializer; public class ExternalExaminationControllerTest extends IntegrationTestCase { @@ -52,13 +53,13 @@ public class ExternalExaminationControllerTest extends IntegrationTestCase { @Rule public final com.icegreen.greenmail.junit4.GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP) - .withConfiguration(new GreenMailConfiguration().withDisabledAuthentication()); + .withConfiguration(new GreenMailConfiguration().withDisabledAuthentication()); @Override protected void onBeforeLogin() throws IOException { - Ebean.deleteAll(Ebean.find(ExamEnrolment.class).findList()); + DB.deleteAll(DB.find(ExamEnrolment.class).findList()); - User user = Ebean.find(User.class, userId == null ? 3L : userId); + User user = DB.find(User.class, userId == null ? 3L : userId); ee = new ExternalExam(); ee.setExternalRef(UUID.randomUUID().toString()); ee.setHash(UUID.randomUUID().toString()); @@ -69,7 +70,7 @@ protected void onBeforeLogin() throws IOException { Files.asCharSource(new File("test/resources/enrolment.json"), StandardCharsets.UTF_8).read() ) ); - ExamRoom room = Ebean.find(ExamRoom.class, 1L); + ExamRoom room = DB.find(ExamRoom.class, 1L); machine = room.getExamMachines().get(0); machine.setIpAddress("127.0.0.1"); // so that the IP check won't fail machine.update(); @@ -135,7 +136,7 @@ public void testCreateStudentExamAlreadyCreated() throws Exception { // Execute Result result = get("/app/student/exam/" + enrolment.getExternalExam().getHash(), true); assertThat(result.status()).isEqualTo(200); - DateTime started = Ebean + DateTime started = DB .find(ExternalExam.class) .where() .eq("hash", enrolment.getExternalExam().getHash()) @@ -148,12 +149,7 @@ public void testCreateStudentExamAlreadyCreated() throws Exception { // Check that starting time did not change assertThat( - Ebean - .find(ExternalExam.class) - .where() - .eq("hash", enrolment.getExternalExam().getHash()) - .findOne() - .getStarted() + DB.find(ExternalExam.class).where().eq("hash", enrolment.getExternalExam().getHash()).findOne().getStarted() ) .isEqualTo(started); } @@ -189,7 +185,7 @@ public void testAnswerMultiChoiceQuestion() throws Exception { assertThat(result.status()).isEqualTo(200); // Check that an option was marked as answered in the database - ExternalExam savedExternalExam = Ebean.find(ExternalExam.class).where().eq("hash", ee.getHash()).findOne(); + ExternalExam savedExternalExam = DB.find(ExternalExam.class).where().eq("hash", ee.getHash()).findOne(); Exam savedExam = savedExternalExam.deserialize(); ExamSectionQuestion savedQuestion = savedExam .getExamSections() @@ -249,66 +245,64 @@ public void testDoExam() throws Exception { .getExamSections() .stream() .flatMap(es -> es.getSectionQuestions().parallelStream()) - .forEach( - esq -> { - Question question = esq.getQuestion(); - Result r; - switch (question.getType()) { - case EssayQuestion: - ObjectNode body = Json.newObject().put("answer", "this is my answer"); - EssayAnswer answer = esq.getEssayAnswer(); - if (answer != null && answer.getObjectVersion() > 0) { - body.put("objectVersion", answer.getObjectVersion()); - } - r = - request( - Helpers.POST, - String.format("/app/iop/student/exam/%s/question/%d", hash, esq.getId()), - body, - true - ); - assertThat(r.status()).isEqualTo(200); - break; - case ClozeTestQuestion: - ObjectNode content = (ObjectNode) Json - .newObject() - .set( - "answer", - Json - .newObject() - .put("1", "this is my answer for cloze 1") - .put("2", "this is my answer for cloze 2") - ); - ClozeTestAnswer clozeAnswer = esq.getClozeTestAnswer(); - if (clozeAnswer != null && clozeAnswer.getObjectVersion() > 0) { - content.put("objectVersion", clozeAnswer.getObjectVersion()); - } - r = - request( - Helpers.POST, - String.format("/app/iop/student/exam/%s/clozetest/%d", hash, esq.getId()), - content - ); - assertThat(r.status()).isEqualTo(200); - break; - default: - Iterator it = esq.getOptions().iterator(); - ExamSectionQuestionOption option = it.next(); - r = - request( - Helpers.POST, - String.format("/app/iop/student/exam/%s/question/%d/option", hash, esq.getId()), - createMultipleChoiceAnswerData(option), - true - ); - assertThat(r.status()).isEqualTo(200); - break; - } + .forEach(esq -> { + Question question = esq.getQuestion(); + Result r; + switch (question.getType()) { + case EssayQuestion: + ObjectNode body = Json.newObject().put("answer", "this is my answer"); + EssayAnswer answer = esq.getEssayAnswer(); + if (answer != null && answer.getObjectVersion() > 0) { + body.put("objectVersion", answer.getObjectVersion()); + } + r = + request( + Helpers.POST, + String.format("/app/iop/student/exam/%s/question/%d", hash, esq.getId()), + body, + true + ); + assertThat(r.status()).isEqualTo(200); + break; + case ClozeTestQuestion: + ObjectNode content = (ObjectNode) Json + .newObject() + .set( + "answer", + Json + .newObject() + .put("1", "this is my answer for cloze 1") + .put("2", "this is my answer for cloze 2") + ); + ClozeTestAnswer clozeAnswer = esq.getClozeTestAnswer(); + if (clozeAnswer != null && clozeAnswer.getObjectVersion() > 0) { + content.put("objectVersion", clozeAnswer.getObjectVersion()); + } + r = + request( + Helpers.POST, + String.format("/app/iop/student/exam/%s/clozetest/%d", hash, esq.getId()), + content + ); + assertThat(r.status()).isEqualTo(200); + break; + default: + Iterator it = esq.getOptions().iterator(); + ExamSectionQuestionOption option = it.next(); + r = + request( + Helpers.POST, + String.format("/app/iop/student/exam/%s/question/%d/option", hash, esq.getId()), + createMultipleChoiceAnswerData(option), + true + ); + assertThat(r.status()).isEqualTo(200); + break; } - ); + }); result = request(Helpers.PUT, String.format("/app/iop/student/exam/%s", hash), null); assertThat(result.status()).isEqualTo(200); - ExternalExam turnedExam = Ebean.find(ExternalExam.class).where().eq("hash", hash).findOne(); + ExternalExam turnedExam = DB.find(ExternalExam.class).where().eq("hash", hash).findOne(); assertThat(turnedExam.getFinished()).isNotNull(); Exam content = turnedExam.deserialize(); assertThat(content.getState()).isEqualTo(Exam.State.REVIEW); diff --git a/test/functional/ByodConfigHandlerTest.java b/test/functional/ByodConfigHandlerTest.java index ad098d2f6f..179695a499 100644 --- a/test/functional/ByodConfigHandlerTest.java +++ b/test/functional/ByodConfigHandlerTest.java @@ -15,8 +15,8 @@ public void testCalculateConfigKey() { app, () -> { ByodConfigHandler bch = app.injector().instanceOf(ByodConfigHandler.class); - String key = bch.calculateConfigKey("123456"); - assertThat(key).isEqualTo("e3c8007ac6b9f8a70b20b9696eb38a13097b22806a85e13f356a6eb45d7800d3"); + String key = bch.calculateConfigKey("123456", "quit"); + assertThat(key).isEqualTo("8bc05b365a8093e0aeb7f4c3c3021a077bf454f12d1e232dcdef2b6f3d1098f7"); } ); } @@ -28,7 +28,7 @@ public void testCreateConfigFile() { () -> { ByodConfigHandler bch = app.injector().instanceOf(ByodConfigHandler.class); byte[] pwd = bch.getEncryptedPassword("password", "salt"); - byte[] data = bch.getExamConfig("123456", pwd, "salt"); + byte[] data = bch.getExamConfig("123456", pwd, "salt", "quit"); // sanity check that we actually have a reasonably sized file content assertThat(data.length).isGreaterThan(1000); } diff --git a/test/resources/application-test.yaml b/test/resources/application-test.yaml new file mode 100644 index 0000000000..7c21316d1d --- /dev/null +++ b/test/resources/application-test.yaml @@ -0,0 +1,4 @@ +ebean: + ddl: + generate: true + run: true diff --git a/test/resources/enrolment.json b/test/resources/enrolment.json index b325158fff..a7ca317e84 100644 --- a/test/resources/enrolment.json +++ b/test/resources/enrolment.json @@ -713,11 +713,11 @@ "examInspections": [{"user":{"id": 4, "lastName":"Penaali","firstName":"Arvon"}}], "examinationDates": [], "enrollInstruction": null, - "examActiveEndDate": null, + "periodEnd": null, "examParticipations": [], "inspectionComments": [], "languageInspection": null, - "examActiveStartDate": null, + "periodStart": null, "autoEvaluationConfig": null, "autoEvaluationNotified": null, "subjectToLanguageInspection": null diff --git a/test/resources/enrolment_with_lottery.json b/test/resources/enrolment_with_lottery.json index 34bb225059..d0764b47a1 100644 --- a/test/resources/enrolment_with_lottery.json +++ b/test/resources/enrolment_with_lottery.json @@ -716,11 +716,11 @@ "examInspections": [{"user":{"id": 4, "lastName":"Penaali","firstName":"Arvon"}}], "examinationDates": [], "enrollInstruction": null, - "examActiveEndDate": null, + "periodEnd": null, "examParticipations": [], "inspectionComments": [], "languageInspection": null, - "examActiveStartDate": null, + "periodStart": null, "autoEvaluationConfig": null, "autoEvaluationNotified": null, "subjectToLanguageInspection": null diff --git a/test/resources/externalExamAttainment.json b/test/resources/externalExamAttainment.json index 9aea3f2aeb..cecc979c5f 100644 --- a/test/resources/externalExamAttainment.json +++ b/test/resources/externalExamAttainment.json @@ -1184,11 +1184,11 @@ "examInspections": [{"user":{"id": 4, "lastName":"Penaali","firstName":"Arvon"}}], "examinationDates": [], "enrollInstruction": null, - "examActiveEndDate": null, + "periodEnd": null, "examParticipations": [], "inspectionComments": [], "languageInspection": null, - "examActiveStartDate": null, + "periodStart": null, "autoEvaluationConfig": { "id": null, "amountDays": null, diff --git a/test/resources/initial-data.yml b/test/resources/initial-data.yml index 2a9b2c634e..786009019c 100644 --- a/test/resources/initial-data.yml +++ b/test/resources/initial-data.yml @@ -631,8 +631,8 @@ exams: examType: *final instruction: Vastaa kolmeen tehtävään neljästä shared: false - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *zerotofive examSections: executionType: *public @@ -658,8 +658,8 @@ exams: examType: *final instruction: Vastaa kolmeen tehtävään neljästä shared: false - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-08-01 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-08-01 16:00:00.123 gradeScale: *zerotofive executionType: *public examSections: @@ -680,8 +680,8 @@ exams: examType: *final instruction: shared: false - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *zerotofive executionType: *public examSections: @@ -700,8 +700,8 @@ exams: examType: *final instruction: Vastaa jompaan kumpaan, Essee tehävään tai monivalintoihin shared: true - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *zerotofive executionType: *public examSections: @@ -719,8 +719,8 @@ exams: examType: *final instruction: Vastaa kaikkiin tenttikysymyksiin shared: true - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *latin executionType: *public examSections: @@ -738,8 +738,8 @@ exams: examType: *final instruction: Tentissä saa käyttää vain O(log(n)) Algoritmeja shared: true - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *approvedrejected executionType: *public examSections: @@ -757,8 +757,8 @@ exams: examType: *final instruction: Tentissä saa käyttää vain tilakoneita. shared: true - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *zerotofive executionType: *public examSections: @@ -776,8 +776,8 @@ exams: examType: *final instruction: Tentissä saa käyttää vain O(log(n)) Algoritmeja shared: true - examActiveStartDate: 2014-05-01 08:00:00.123 - examActiveEndDate: 2014-12-29 16:00:00.123 + periodStart: 2014-05-01 08:00:00.123 + periodEnd: 2014-12-29 16:00:00.123 gradeScale: *approvedrejected executionType: *public examSections: @@ -1323,60 +1323,6 @@ exam-rooms: outOfService: false state: ACTIVE -################################################################ - -calendar-events: - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 16:00:00.000 - weekday: MONDAY - timezoneOffset: 7200000 - room: *room-pegasus - - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 16:00:00.000 - weekday: TUESDAY - timezoneOffset: 7200000 - room: *room-pegasus - - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 16:00:00.000 - weekday: WEDNESDAY - timezoneOffset: 7200000 - room: *room-pegasus - - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 16:00:00.000 - weekday: THURSDAY - timezoneOffset: 7200000 - room: *room-pegasus - - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 16:00:00.000 - weekday: FRIDAY - timezoneOffset: 7200000 - room: *room-pegasus - - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 16:00:00.000 - weekday: SATURDAY - timezoneOffset: 7200000 - room: *room-pegasus - - - !!models.calendar.DefaultWorkingHours - startTime: 2014-05-05 08:00:00.000 - endTime: 2014-05-05 21:00:00.000 - weekday: SUNDAY - timezoneOffset: 7200000 - room: *room-pegasus - -################################################################ - exam-machines: - &exam-machine1 !!models.ExamMachine diff --git a/test/resources/test-ebean.properties b/test/resources/test-ebean.properties deleted file mode 100644 index d95131a38e..0000000000 --- a/test/resources/test-ebean.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright (c) 2018 Exam Consortium -# -# Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent -# versions of the EUPL (the "Licence"); -# You may not use this work except in compliance with the Licence. -# You may obtain a copy of the Licence at: -# -# https://joinup.ec.europa.eu/software/page/eupl/licence-eupl -# -# Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed -# on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the Licence for the specific language governing permissions and limitations under the Licence. -# -# - -ebean.ddl.generate=true -ebean.ddl.run=true \ No newline at end of file diff --git a/ui/.eslintrc.json b/ui/.eslintrc.json index 8cb50ac7da..1f2a9bb4b3 100644 --- a/ui/.eslintrc.json +++ b/ui/.eslintrc.json @@ -1,54 +1,50 @@ { - "root": true, - "ignorePatterns": [ - "projects/**/*" - ], - "overrides": [ - { - "files": [ - "*.ts" - ], - "parserOptions": { - "project": [ - "tsconfig.json" - ], - "createDefaultProgram": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@angular-eslint/recommended", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "error", - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "xm", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "xm", - "style": "kebab-case" - } - ], - "@typescript-eslint/member-ordering": "error" - } - }, - { - "files": [ - "*.html" - ], - "extends": [ - "plugin:@angular-eslint/template/recommended" - ], - "rules": {} - } - ] + "root": true, + "ignorePatterns": ["projects/**/*"], + "overrides": [ + { + "files": ["*.ts"], + "parserOptions": { + "project": ["ui/tsconfig.json"], + "createDefaultProgram": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates", + "plugin:deprecation/recommended" + ], + "plugins": ["no-relative-import-paths"], + "rules": { + "@typescript-eslint/no-explicit-any": "error", + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "xm", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "xm", + "style": "kebab-case" + } + ], + "@typescript-eslint/member-ordering": "error", + "no-relative-import-paths/no-relative-import-paths": [ + "error", + { "allowSameFolder": true, "rootDir": "ui" } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@angular-eslint/template/recommended"], + "rules": {} + } + ] } diff --git a/ui/.husky/pre-commit b/ui/.husky/pre-commit deleted file mode 100755 index c7e81ea6bb..0000000000 --- a/ui/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -cd ui && npx lint-staged diff --git a/ui/.npmrc b/ui/.npmrc deleted file mode 100644 index b6f27f1359..0000000000 --- a/ui/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true diff --git a/ui/.prettierrc.js b/ui/.prettierrc.js deleted file mode 100644 index c8c6a54961..0000000000 --- a/ui/.prettierrc.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - semi: true, - trailingComma: 'all', - singleQuote: true, - printWidth: 120, - tabWidth: 4, -}; diff --git a/ui/.prettierrc.yaml b/ui/.prettierrc.yaml new file mode 100644 index 0000000000..f2a38ea39b --- /dev/null +++ b/ui/.prettierrc.yaml @@ -0,0 +1,7 @@ +semi: true +trailingComma: 'all' +singleQuote: true +printWidth: 120 +tabWidth: 4 +plugins: + - 'prettier-plugin-organize-imports' diff --git a/ui/package-lock.json b/ui/package-lock.json deleted file mode 100644 index da94d40ee5..0000000000 --- a/ui/package-lock.json +++ /dev/null @@ -1,26794 +0,0 @@ -{ - "name": "exam", - "version": "6.2.3", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "exam", - "version": "6.2.3", - "license": "EUPL-1.1", - "dependencies": { - "@angular/animations": "^15.1.5", - "@angular/cdk": "^15.1.5", - "@angular/common": "^15.1.5", - "@angular/compiler": "^15.1.5", - "@angular/core": "^15.1.5", - "@angular/forms": "^15.1.5", - "@angular/localize": "^15.1.5", - "@angular/platform-browser": "^15.1.5", - "@angular/platform-browser-dynamic": "^15.1.5", - "@angular/router": "^15.1.5", - "@fullcalendar/angular": "^6.0.3", - "@fullcalendar/luxon2": "^6.0.3", - "@fullcalendar/timegrid": "^6.0.3", - "@ng-bootstrap/ng-bootstrap": "^14.0.1", - "@ngx-translate/core": "^14.0.0", - "@ngx-translate/http-loader": "^7.0.0", - "@popperjs/core": "^2.10.2", - "bootstrap": "~5.2.0", - "bootstrap-icons": "^1.3.0", - "chart.js": "^3.8.0", - "chartjs-plugin-datalabels": "^2.0.0", - "date-fns": "^2.25.0", - "file-saver-es": "^2.0.5", - "luxon": "^2.0.0", - "ngx-toastr": "^16.0.2", - "ngx-webstorage-service": "^5.0.0", - "ramda": "^0.28.0", - "rxjs": "^7.4.0", - "zone.js": "^0.11.4" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^15.1.6", - "@angular-eslint/builder": "^15.2.1", - "@angular-eslint/eslint-plugin": "^15.2.1", - "@angular-eslint/eslint-plugin-template": "^15.2.1", - "@angular-eslint/schematics": "^15.2.1", - "@angular-eslint/template-parser": "^15.2.1", - "@angular/cli": "^15.1.6", - "@angular/compiler-cli": "^15.1.5", - "@types/ckeditor": "^4.9.10", - "@types/file-saver-es": "^2.0.1", - "@types/jasmine": "^3.10.0", - "@types/luxon": "^3.1.0", - "@types/mathjax": "^0.0.37", - "@types/ramda": "^0.28.14", - "@typescript-eslint/eslint-plugin": "^5.43.0", - "@typescript-eslint/parser": "^5.43.0", - "eslint": "^8.28.0", - "husky": "^8.0.1", - "jasmine-core": "^4.0.0", - "karma": "^6.3.0", - "karma-chrome-launcher": "^3.1.0", - "karma-coverage": "^2.1.0", - "karma-jasmine": "^4.0.0", - "karma-jasmine-html-reporter": "^1.7.0", - "lint-staged": "^13.0.3", - "prettier": "^2.6.1", - "prettier-plugin-java": "^1.6.1", - "prettier-plugin-organize-imports": "^3.0.0", - "typescript": "~4.9.5", - "webpack": "^5.76.0", - "webpack-bundle-analyzer": "^4.5.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@angular-devkit/architect": { - "version": "0.1502.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1502.10.tgz", - "integrity": "sha512-S8lN73WYCfpEpw1Q41ZcUinw7JfDeSM8LyGs797OVshnW75QcOkOecWj/3CKR23G44IgFrHN6sqtzWxKmMxLig==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "15.2.10", - "rxjs": "6.6.7" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/architect/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/architect/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-15.2.10.tgz", - "integrity": "sha512-3pCPVEJilVwHIJC6Su1/PIEqvFfU1Lxew9yItxX4s6dud8HY+fuKrsDnao4NNMFNqCLqL4el5QbSBKnnpWH1sg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.2.0", - "@angular-devkit/architect": "0.1502.10", - "@angular-devkit/build-webpack": "0.1502.10", - "@angular-devkit/core": "15.2.10", - "@babel/core": "7.20.12", - "@babel/generator": "7.20.14", - "@babel/helper-annotate-as-pure": "7.18.6", - "@babel/helper-split-export-declaration": "7.18.6", - "@babel/plugin-proposal-async-generator-functions": "7.20.7", - "@babel/plugin-transform-async-to-generator": "7.20.7", - "@babel/plugin-transform-runtime": "7.19.6", - "@babel/preset-env": "7.20.2", - "@babel/runtime": "7.20.13", - "@babel/template": "7.20.7", - "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "15.2.10", - "ansi-colors": "4.1.3", - "autoprefixer": "10.4.13", - "babel-loader": "9.1.2", - "babel-plugin-istanbul": "6.1.1", - "browserslist": "4.21.5", - "cacache": "17.0.4", - "chokidar": "3.5.3", - "copy-webpack-plugin": "11.0.0", - "critters": "0.0.16", - "css-loader": "6.7.3", - "esbuild-wasm": "0.17.8", - "glob": "8.1.0", - "https-proxy-agent": "5.0.1", - "inquirer": "8.2.4", - "jsonc-parser": "3.2.0", - "karma-source-map-support": "1.4.0", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "4.0.2", - "loader-utils": "3.2.1", - "magic-string": "0.29.0", - "mini-css-extract-plugin": "2.7.2", - "open": "8.4.1", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", - "piscina": "3.2.0", - "postcss": "8.4.31", - "postcss-loader": "7.0.2", - "resolve-url-loader": "5.0.0", - "rxjs": "6.6.7", - "sass": "1.58.1", - "sass-loader": "13.2.0", - "semver": "7.5.3", - "source-map-loader": "4.0.1", - "source-map-support": "0.5.21", - "terser": "5.16.3", - "text-table": "0.2.0", - "tree-kill": "1.2.2", - "tslib": "2.5.0", - "webpack": "5.76.1", - "webpack-dev-middleware": "6.0.1", - "webpack-dev-server": "4.11.1", - "webpack-merge": "5.8.0", - "webpack-subresource-integrity": "5.1.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "optionalDependencies": { - "esbuild": "0.17.8" - }, - "peerDependencies": { - "@angular/compiler-cli": "^15.0.0", - "@angular/localize": "^15.0.0", - "@angular/platform-server": "^15.0.0", - "@angular/service-worker": "^15.0.0", - "karma": "^6.3.0", - "ng-packagr": "^15.0.0", - "protractor": "^7.0.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=4.8.2 <5.0" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "karma": { - "optional": true - }, - "ng-packagr": { - "optional": true - }, - "protractor": { - "optional": true - }, - "tailwindcss": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack": { - "version": "5.76.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", - "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-webpack": { - "version": "0.1502.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1502.10.tgz", - "integrity": "sha512-55b9WZIGU4DNgiIV2lkkN6iQxJrgWY5CDaNu0kJC/qazotJgBbcN/8jgBx2DD8HNE1V3iXxWk66pt1h946Po+Q==", - "dev": true, - "dependencies": { - "@angular-devkit/architect": "0.1502.10", - "rxjs": "6.6.7" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "webpack": "^5.30.0", - "webpack-dev-server": "^4.0.0" - } - }, - "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/build-webpack/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@angular-devkit/core": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.10.tgz", - "integrity": "sha512-bFPm7wjvfBds9km2rCJxUhzkqe4h3h/199yJtzC1bNvwRr2LMHvtyoQAzftda+gs7Ulqac5wzUEZX/cVV3WrsA==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "6.6.7", - "source-map": "0.7.4" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@angular-devkit/schematics": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-15.2.10.tgz", - "integrity": "sha512-EeoDs4oKFpLZNa21G/8dqBdclEc4U2piI9EeXCVTaN6z5DYXIZ0G1WtCXU8nhD+GckS47rmfZ4/3lMaXAvED+g==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "15.2.10", - "jsonc-parser": "3.2.0", - "magic-string": "0.29.0", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@angular-eslint/builder": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-15.2.1.tgz", - "integrity": "sha512-7x2DANebLRl997Mj4DhZrnz5+vnSjavGGveJ0mBuU7CEsL0ZYLftdRqL0e0HtU3ksseS7xpchD6OM08nkNgySw==", - "dev": true, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-15.2.1.tgz", - "integrity": "sha512-LO7Am8eVCr7oh6a0VmKSL7K03CnQEQhFO7Wt/YtbfYOxVjrbwmYLwJn+wZPOT7A02t/BttOD/WXuDrOWtSMQ/Q==", - "dev": true - }, - "node_modules/@angular-eslint/eslint-plugin": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-15.2.1.tgz", - "integrity": "sha512-OM7b1kS4E4CkXjkaWN+lEzawh4VxY6l7FO1Cuk4s7iv3/YpZG3rJxIZBqnFLTixwrBuqw8y4FNBzF3eDgmFAUw==", - "dev": true, - "dependencies": { - "@angular-eslint/utils": "15.2.1", - "@typescript-eslint/utils": "5.48.2" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-15.2.1.tgz", - "integrity": "sha512-IeiSLk6YxapFdH2z5o/O3R7VwtBd2T6fWmhLFPwDYMDknrwegnOjwswCdBplOccpUp0wqlCeGUx7LTsuzwaz7w==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "15.2.1", - "@angular-eslint/utils": "15.2.1", - "@typescript-eslint/type-utils": "5.48.2", - "@typescript-eslint/utils": "5.48.2", - "aria-query": "5.1.3", - "axobject-query": "3.1.1" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/schematics": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-15.2.1.tgz", - "integrity": "sha512-0ZfBCejHWIcgy3J5kFs9sS/jqi8i5AptxggOwFySOlCLJ+CzNrktjD4jff1Zy8K/VLzY0Ci0BSZXvgWfP0k9Rg==", - "dev": true, - "dependencies": { - "@angular-eslint/eslint-plugin": "15.2.1", - "@angular-eslint/eslint-plugin-template": "15.2.1", - "ignore": "5.2.4", - "strip-json-comments": "3.1.1", - "tmp": "0.2.1" - }, - "peerDependencies": { - "@angular/cli": ">= 15.0.0 < 16.0.0" - } - }, - "node_modules/@angular-eslint/template-parser": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-15.2.1.tgz", - "integrity": "sha512-ViCi79gC2aKJecmYLkOT+QlT5WMRNXeYz0Dr9Pr8qXzIbY0oAWE7nOT5jkXwQ9oUk+ybtGCWHma5JVJWVJsIog==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "15.2.1", - "eslint-scope": "^7.0.0" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/utils": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-15.2.1.tgz", - "integrity": "sha512-++FneAJHxJqcSu0igVN6uOkSoHxlzgLoMBswuovYJy3UKwm33/T6WFku8++753Ca/JucIoR1gdUfO7SoSspMDg==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "15.2.1", - "@typescript-eslint/utils": "5.48.2" - }, - "peerDependencies": { - "eslint": "^7.20.0 || ^8.0.0", - "typescript": "*" - } - }, - "node_modules/@angular/animations": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-15.2.10.tgz", - "integrity": "sha512-yxfN8qQpMaukRU5LjFkJBmy85rqrOp86tYVCsf+hmPEFRiXBMUj6xYLeCMcpk3Mt1JtnWGBR34ivGx+7bNeAow==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/core": "15.2.10" - } - }, - "node_modules/@angular/cdk": { - "version": "15.2.9", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-15.2.9.tgz", - "integrity": "sha512-koaM07N1AIQ5oHU27l0/FoQSSoYAwlAYwVZ4Di3bYrJsTBNCN2Xsby7wI8gZxdepMnV4Fe9si382BDBov+oO4Q==", - "dependencies": { - "tslib": "^2.3.0" - }, - "optionalDependencies": { - "parse5": "^7.1.2" - }, - "peerDependencies": { - "@angular/common": "^15.0.0 || ^16.0.0", - "@angular/core": "^15.0.0 || ^16.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/cli": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-15.2.10.tgz", - "integrity": "sha512-/TSnm/ZQML6A4lvunyN2tjTB5utuvk3d1Pnfyehp/FXtV6YfZm6+EZrOpKkKPCxTuAgW6c9KK4yQtt3RuNVpwQ==", - "dev": true, - "dependencies": { - "@angular-devkit/architect": "0.1502.10", - "@angular-devkit/core": "15.2.10", - "@angular-devkit/schematics": "15.2.10", - "@schematics/angular": "15.2.10", - "@yarnpkg/lockfile": "1.1.0", - "ansi-colors": "4.1.3", - "ini": "3.0.1", - "inquirer": "8.2.4", - "jsonc-parser": "3.2.0", - "npm-package-arg": "10.1.0", - "npm-pick-manifest": "8.0.1", - "open": "8.4.1", - "ora": "5.4.1", - "pacote": "15.1.0", - "resolve": "1.22.1", - "semver": "7.5.3", - "symbol-observable": "4.0.0", - "yargs": "17.6.2" - }, - "bin": { - "ng": "bin/ng.js" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/common": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-15.2.10.tgz", - "integrity": "sha512-jdBn3fctkqoNrJn9VLsUHpcCEhCxWSczdsR+BBbD6T0oLl6vMrAVNjPwfBejnlgfWN1KoRU9kgOYsMxa5apIWQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/core": "15.2.10", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/compiler": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-15.2.10.tgz", - "integrity": "sha512-M0XkeU0O73UlJZwDvOyp8/apetz9UKj78eTFDseMYJDLcxe6MpkbkxqpsGZnKYDj7LIep8PmCAKEkhtenE82zw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/core": "15.2.10" - }, - "peerDependenciesMeta": { - "@angular/core": { - "optional": true - } - } - }, - "node_modules/@angular/compiler-cli": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-15.2.10.tgz", - "integrity": "sha512-mCFIxrs60XicKfA2o42hA7LrQvhybi9BQveWuZn/2iIEOXx7R62Iemz8E21pLWftAZHGxEW3NECfBrY1d3gVmA==", - "dependencies": { - "@babel/core": "7.19.3", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^3.0.0", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.11.0", - "magic-string": "^0.27.0", - "reflect-metadata": "^0.1.2", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^17.2.1" - }, - "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js", - "ngcc": "bundles/ngcc/main-ngcc.js" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/compiler": "15.2.10", - "typescript": ">=4.8.2 <5.0" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular/compiler-cli/node_modules/magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular/core": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-15.2.10.tgz", - "integrity": "sha512-meGGidnitQJGDxYd9/LrqYiVlId+vGaLoiLgJdKBz+o2ZO6OmXQGuNw2VBqf17/Cc0/UjzrOY7+kILNFKkk/WQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.11.4 || ~0.12.0 || ~0.13.0" - } - }, - "node_modules/@angular/forms": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-15.2.10.tgz", - "integrity": "sha512-NIntGsNcN6o8L1txsbWXOf6f3K/CUBizdKsxsYVYGJIXEW5qU6UnWmfAZffNNXsT/XvbgUCjgDwT0cAwcqZPuQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/common": "15.2.10", - "@angular/core": "15.2.10", - "@angular/platform-browser": "15.2.10", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/localize": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-15.2.10.tgz", - "integrity": "sha512-RHN+mUR4H34c/LLnNPAyQbfuZME4i9JgodK5YRRX8cSAFPafYLT0SspSuLsKtcCCEDadAZNDHzb8qv5MBtzJtg==", - "dependencies": { - "@babel/core": "7.19.3", - "glob": "8.1.0", - "yargs": "^17.2.1" - }, - "bin": { - "localize-extract": "tools/bundles/src/extract/cli.js", - "localize-migrate": "tools/bundles/src/migrate/cli.js", - "localize-translate": "tools/bundles/src/translate/cli.js" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/compiler": "15.2.10", - "@angular/compiler-cli": "15.2.10" - } - }, - "node_modules/@angular/localize/node_modules/@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/localize/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular/platform-browser": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.10.tgz", - "integrity": "sha512-9tbgVGSJqwfrOzT8aA/kWBLNhJSQ9gUg0CJxwFBSJm8VkBUJrszoBlDsnSvlxx8/W2ejNULKHFTXeUzq0O/+RQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/animations": "15.2.10", - "@angular/common": "15.2.10", - "@angular/core": "15.2.10" - }, - "peerDependenciesMeta": { - "@angular/animations": { - "optional": true - } - } - }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.10.tgz", - "integrity": "sha512-JHP6W+FX715Qv7DhqvfZLuBZXSDJrboiQsR06gUAgDSjAUyhbqmpVg/2YOtgeWpPkzNDtXdPU2PhcRdIv5J3Yg==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/common": "15.2.10", - "@angular/compiler": "15.2.10", - "@angular/core": "15.2.10", - "@angular/platform-browser": "15.2.10" - } - }, - "node_modules/@angular/router": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-15.2.10.tgz", - "integrity": "sha512-LmuqEg0iIXSw7bli6HKJ19cbxP91v37GtRwbGKswyLihqzTgvjBYpvcfMnB5FRQ5LWkTwq5JclkX03dZw290Yg==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" - }, - "peerDependencies": { - "@angular/common": "15.2.10", - "@angular/core": "15.2.10", - "@angular/platform-browser": "15.2.10", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@assemblyscript/loader": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", - "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", - "dev": true - }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.20.14", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", - "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", - "dependencies": { - "@babel/types": "^7.20.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", - "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", - "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name/node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dependencies": { - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers/node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", - "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", - "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-static-block instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-json-strings instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-logical-assignment-operators instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", - "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", - "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", - "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", - "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", - "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", - "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", - "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", - "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", - "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", - "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", - "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", - "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", - "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", - "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", - "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", - "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", - "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz", - "integrity": "sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", - "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", - "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", - "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", - "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", - "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", - "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz", - "integrity": "sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz", - "integrity": "sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz", - "integrity": "sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz", - "integrity": "sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz", - "integrity": "sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz", - "integrity": "sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz", - "integrity": "sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz", - "integrity": "sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz", - "integrity": "sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz", - "integrity": "sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz", - "integrity": "sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz", - "integrity": "sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz", - "integrity": "sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz", - "integrity": "sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz", - "integrity": "sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz", - "integrity": "sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz", - "integrity": "sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz", - "integrity": "sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz", - "integrity": "sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz", - "integrity": "sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz", - "integrity": "sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz", - "integrity": "sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@fullcalendar/angular": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.9.tgz", - "integrity": "sha512-cN91zGQEGM9s6VnD+2jNdHomAGHJIGSMBR0ts5gJC0FIRCuLtjDxiZN4kNfRWxx7NJiSLm+NCKijo6317pGhsw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/common": "12 - 16", - "@angular/core": "12 - 16", - "@fullcalendar/core": "~6.1.9" - } - }, - "node_modules/@fullcalendar/core": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.9.tgz", - "integrity": "sha512-eeG+z9BWerdsU9Ac6j16rpYpPnE0wxtnEHiHrh/u/ADbGTR3hCOjCD9PxQOfhOTHbWOVs7JQunGcksSPu5WZBQ==", - "peer": true, - "dependencies": { - "preact": "~10.12.1" - } - }, - "node_modules/@fullcalendar/daygrid": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.9.tgz", - "integrity": "sha512-o/6joH/7lmVHXAkbaa/tUbzWYnGp/LgfdiFyYPkqQbjKEeivNZWF1WhHqFbhx0zbFONSHtrvkjY2bjr+Ef2quQ==", - "peerDependencies": { - "@fullcalendar/core": "~6.1.9" - } - }, - "node_modules/@fullcalendar/luxon2": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/luxon2/-/luxon2-6.1.9.tgz", - "integrity": "sha512-HbHbk+iwBv0PpM8WPA3U6mI0OTSfTMSD31+3PlKh3/YKjpYnG6ITzoh1yjS4Fg1Yas/t6OCQHCuW02st0HUEJQ==", - "peerDependencies": { - "@fullcalendar/core": "~6.1.9", - "luxon": "^2.0.0" - } - }, - "node_modules/@fullcalendar/timegrid": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.9.tgz", - "integrity": "sha512-le7UV05wVE1Trdr054kgJXTwa+A1pEI8nlCBnPWdcyrL+dTLoPvQ4AWEVCnV7So+4zRYaCqnqGXfCJsj0RQa0g==", - "dependencies": { - "@fullcalendar/daygrid": "~6.1.9" - }, - "peerDependencies": { - "@fullcalendar/core": "~6.1.9" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "node_modules/@ng-bootstrap/ng-bootstrap": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-14.2.0.tgz", - "integrity": "sha512-nqEKVXauSontGKqC5WSKpch5TiAGDZB3hluvxkINS0r9LUE6sBQRP3qeYOe7Uwu+UbQcj28NG3qFHhpfnG8KHw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/common": "^15.0.0", - "@angular/core": "^15.0.0", - "@angular/forms": "^15.0.0", - "@angular/localize": "^15.0.0", - "@popperjs/core": "^2.11.6", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@ngtools/webpack": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.10.tgz", - "integrity": "sha512-ZExB4rKh/Saad31O/Ofd2XvRuILuCNTYs0+qJL697Be2pzeewvzBhE4Xe1Mm7Jg13aWSPeuIdzSGOqCdwxxxFQ==", - "dev": true, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^15.0.0", - "typescript": ">=4.8.2 <5.0", - "webpack": "^5.54.0" - } - }, - "node_modules/@ngx-translate/core": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", - "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/core": ">=13.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@ngx-translate/http-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz", - "integrity": "sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/common": ">=13.0.0", - "@ngx-translate/core": ">=14.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/git": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", - "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", - "dev": true, - "dependencies": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", - "dev": true, - "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "bin": { - "installed-package-contents": "lib/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", - "dev": true, - "dependencies": { - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/run-script": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", - "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", - "dev": true, - "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/run-script/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.23", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", - "dev": true - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@schematics/angular": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-15.2.10.tgz", - "integrity": "sha512-eLdyP+T1TueNQ8FCP7sP+tt8z+YQ1BINsJsyAyoJT/XZjcCV7LUxgDIU94/kuvIotmJ2xTuFWHFPfAY+CN3duQ==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "15.2.10", - "@angular-devkit/schematics": "15.2.10", - "jsonc-parser": "3.2.0" - }, - "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@sigstore/bundle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", - "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", - "dev": true, - "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/protobuf-specs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", - "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", - "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", - "dev": true, - "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "make-fetch-happen": "^11.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sigstore/sign/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/@sigstore/sign/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@sigstore/tuf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", - "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", - "dev": true, - "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0", - "tuf-js": "^1.1.7" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", - "dev": true - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tufjs/canonical-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", - "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@tufjs/models": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", - "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", - "dev": true, - "dependencies": { - "@tufjs/canonical-json": "1.0.0", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@tufjs/models/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", - "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", - "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ckeditor": { - "version": "4.9.10", - "resolved": "https://registry.npmjs.org/@types/ckeditor/-/ckeditor-4.9.10.tgz", - "integrity": "sha512-dcOPCXM0Cr5Z0i6eF/aW5LvECrS+cdl2Gi7lU+rEUNWby0w9Yl6mBubjrs29OVAducpuZjB4mfDayE+o4/gGdQ==", - "dev": true - }, - "node_modules/@types/connect": { - "version": "3.4.37", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", - "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", - "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true - }, - "node_modules/@types/cors": { - "version": "2.8.15", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.15.tgz", - "integrity": "sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.44.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", - "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", - "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", - "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.39", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", - "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/file-saver-es": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/file-saver-es/-/file-saver-es-2.0.2.tgz", - "integrity": "sha512-f9S7EJ0wHHpomR5EhQt4w6hYrewSOjdvTvPxDDZPPdB7CTrjyRHxx4htbIHkGN7CVe3j9nJaJ9d2VIZr3QZUTQ==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", - "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.13", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", - "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/jasmine": { - "version": "3.10.15", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.15.tgz", - "integrity": "sha512-NdWern4OhbU7QcdlpPnvqy7LqpEjiAQ47tHDRdUKyGcwnhdmTsGniSJCC2B9ODiYiRnP53v6HOzu8B5/bqOtUw==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", - "dev": true - }, - "node_modules/@types/luxon": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.3.tgz", - "integrity": "sha512-/BJF3NT0pRMuxrenr42emRUF67sXwcZCd+S1ksG/Fcf9O7C3kKCY4uJSbKBE4KDUIYr3WMsvfmWD8hRjXExBJQ==", - "dev": true - }, - "node_modules/@types/mathjax": { - "version": "0.0.37", - "resolved": "https://registry.npmjs.org/@types/mathjax/-/mathjax-0.0.37.tgz", - "integrity": "sha512-y0WSZBtBNQwcYipTU/BhgeFu1EZNlFvUNCmkMXV9kBQZq7/o5z82dNVyH3yy2Xv5zzeNeQoHSL4Xm06+EQiH+g==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", - "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", - "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", - "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", - "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", - "dev": true - }, - "node_modules/@types/ramda": { - "version": "0.28.25", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.25.tgz", - "integrity": "sha512-HrQNqQAGcITpn9HAJFamDxm7iZeeXiP/95pN5OMbNniDjzCCeOHbBKNGmUy8NRi0fhYS+/cXeo91MFC+06gbow==", - "dev": true, - "dependencies": { - "ts-toolbelt": "^6.15.1" - } - }, - "node_modules/@types/range-parser": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", - "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", - "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", - "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", - "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.35", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", - "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", - "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.2.tgz", - "integrity": "sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.48.2", - "@typescript-eslint/utils": "5.48.2", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", - "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", - "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/visitor-keys": "5.48.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", - "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.2.tgz", - "integrity": "sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.48.2", - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/typescript-estree": "5.48.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", - "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/visitor-keys": "5.48.2" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", - "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", - "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/visitor-keys": "5.48.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", - "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dev": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/babel-loader": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.2.tgz", - "integrity": "sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==", - "dev": true, - "dependencies": { - "find-cache-dir": "^3.3.2", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true, - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, - "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/bootstrap": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", - "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/twbs" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - } - ], - "peerDependencies": { - "@popperjs/core": "^2.11.6" - } - }, - "node_modules/bootstrap-icons": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.1.tgz", - "integrity": "sha512-F0DDp7nKUX+x/QtpfRZ+XHFya60ng9nfdpdS59vDDfs4Uhuxp7zym/QavMsu/xx51txkoM9eVmpE7D08N35blw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/twbs" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - } - ] - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacache": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz", - "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^8.0.1", - "lru-cache": "^7.7.1", - "minipass": "^4.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" - }, - "node_modules/chartjs-plugin-datalabels": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", - "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", - "peerDependencies": { - "chart.js": ">=3.0.0" - } - }, - "node_modules/chevrotain": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-6.5.0.tgz", - "integrity": "sha512-BwqQ/AgmKJ8jcMEjaSnfMybnKMgGTrtDKowfTP3pX4jwVy0kNjRsT/AP6h+wC3+3NC+X8X15VWBnTCQlX+wQFg==", - "dev": true, - "dependencies": { - "regexp-to-ast": "0.4.0" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", - "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "dependencies": { - "is-what": "^3.14.1" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.1", - "globby": "^13.1.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/core-js-compat": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", - "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.22.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat/node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/critters": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.16.tgz", - "integrity": "sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "css-select": "^4.2.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "postcss": "^8.3.7", - "pretty-bytes": "^5.3.0" - } - }, - "node_modules/critters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/critters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/critters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/critters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/critters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/critters/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/critters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-loader": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", - "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.19", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", - "dev": true - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/date-fns/node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/date-fns/node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" - }, - "node_modules/date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/default-gateway/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/default-gateway/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-gateway/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", - "dev": true, - "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.569", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", - "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/engine.io": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", - "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", - "dev": true, - "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", - "dev": true - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz", - "integrity": "sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.17.8", - "@esbuild/android-arm64": "0.17.8", - "@esbuild/android-x64": "0.17.8", - "@esbuild/darwin-arm64": "0.17.8", - "@esbuild/darwin-x64": "0.17.8", - "@esbuild/freebsd-arm64": "0.17.8", - "@esbuild/freebsd-x64": "0.17.8", - "@esbuild/linux-arm": "0.17.8", - "@esbuild/linux-arm64": "0.17.8", - "@esbuild/linux-ia32": "0.17.8", - "@esbuild/linux-loong64": "0.17.8", - "@esbuild/linux-mips64el": "0.17.8", - "@esbuild/linux-ppc64": "0.17.8", - "@esbuild/linux-riscv64": "0.17.8", - "@esbuild/linux-s390x": "0.17.8", - "@esbuild/linux-x64": "0.17.8", - "@esbuild/netbsd-x64": "0.17.8", - "@esbuild/openbsd-x64": "0.17.8", - "@esbuild/sunos-x64": "0.17.8", - "@esbuild/win32-arm64": "0.17.8", - "@esbuild/win32-ia32": "0.17.8", - "@esbuild/win32-x64": "0.17.8" - } - }, - "node_modules/esbuild-wasm": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.17.8.tgz", - "integrity": "sha512-zCmpxv95E0FuCmvdw1K836UHnj4EdiQnFfjTby35y3LAjRPtXMj3sbHDRHjbD8Mqg5lTwq3knacr/1qIFU51CQ==", - "dev": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter-asyncresource": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", - "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", - "dev": true - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-saver-es": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/file-saver-es/-/file-saver-es-2.0.5.tgz", - "integrity": "sha512-Kg0lt+is9nOyi/VDms9miScNGot25jVFbjFccXuCL/shd2Q+rt70MALxHVkXllsX83JEBLiHQNjDPGd/6FIOoQ==" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hdr-histogram-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", - "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", - "dev": true, - "dependencies": { - "@assemblyscript/loader": "^0.10.1", - "base64-js": "^1.2.0", - "pako": "^1.0.3" - } - }, - "node_modules/hdr-histogram-percentiles-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", - "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", - "dev": true - }, - "node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-walk": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", - "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", - "dev": true, - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/immutable": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", - "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/inquirer": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", - "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/inquirer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jasmine-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", - "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", - "dev": true - }, - "node_modules/java-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-2.0.2.tgz", - "integrity": "sha512-fwv1eDYE4OIAN+XS7cD8aB7UdQyAh3Uz36ydWqemvnDKXEdLbxq7qIbvsjpSvS1NHFR+r81N7AjGcpnamjVxJw==", - "dev": true, - "dependencies": { - "chevrotain": "6.5.0", - "lodash": "4.17.21" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/karma": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", - "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", - "dev": true, - "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/karma-chrome-launcher": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", - "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", - "dev": true, - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-chrome-launcher/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/karma-coverage": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", - "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/karma-jasmine": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.2.tgz", - "integrity": "sha512-ggi84RMNQffSDmWSyyt4zxzh2CQGwsxvYYsprgyR1j8ikzIduEdOlcLvXjZGwXG/0j41KUXOWsUCBfbEHPWP9g==", - "dev": true, - "dependencies": { - "jasmine-core": "^3.6.0" - }, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "karma": "*" - } - }, - "node_modules/karma-jasmine-html-reporter": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", - "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", - "dev": true, - "peerDependencies": { - "jasmine-core": ">=3.8", - "karma": ">=0.9", - "karma-jasmine": ">=1.1" - } - }, - "node_modules/karma-jasmine/node_modules/jasmine-core": { - "version": "3.99.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", - "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", - "dev": true - }, - "node_modules/karma-source-map-support": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", - "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", - "dev": true, - "dependencies": { - "source-map-support": "^0.5.5" - } - }, - "node_modules/karma/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/karma/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/karma/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/karma/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", - "dev": true, - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, - "node_modules/less-loader": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", - "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", - "dev": true, - "dependencies": { - "klona": "^2.0.4" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "less": "^3.5.0 || ^4.0.0", - "webpack": "^5.0.0" - } - }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/license-webpack-plugin": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", - "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", - "dev": true, - "dependencies": { - "webpack-sources": "^3.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-sources": { - "optional": true - } - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lint-staged": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz", - "integrity": "sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ==", - "dev": true, - "dependencies": { - "chalk": "5.3.0", - "commander": "11.0.0", - "debug": "4.3.4", - "execa": "7.2.0", - "lilconfig": "2.1.0", - "listr2": "6.6.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.1" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/listr2": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", - "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", - "dev": true, - "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", - "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/listr2/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "node_modules/listr2/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", - "dev": true, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, - "node_modules/lodash.invokemap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", - "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.pullall": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.pullall/-/lodash.pullall-4.2.0.tgz", - "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==", - "dev": true - }, - "node_modules/lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", - "dev": true, - "dependencies": { - "ansi-escapes": "^5.0.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", - "dev": true, - "dependencies": { - "type-fest": "^1.0.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/log-update/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/log-update/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", - "dev": true, - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/luxon": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz", - "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/magic-string": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", - "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/make-fetch-happen/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", - "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-fetch/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", - "dev": true, - "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "node_modules/minipass-json-stream/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-json-stream/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/needle": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", - "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/ngx-toastr": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-16.2.0.tgz", - "integrity": "sha512-7X6UhOKiaUeC2eTOsUqctZH0ZWKG8VlzDxWJhdEF1N3kPod46SU/Vn2l0hbt8EDwTjxHKfKyevU2idkYDoZYog==", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/common": ">=14.0.0-0", - "@angular/core": ">=14.0.0-0", - "@angular/platform-browser": ">=14.0.0-0" - } - }, - "node_modules/ngx-webstorage-service": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ngx-webstorage-service/-/ngx-webstorage-service-5.0.0.tgz", - "integrity": "sha512-adipYzdVGA1HxPF5n62eJoQGohiJRlpCp7lPuNQcOvkHGfFUByAfXZHmmLFzb5OFfeNWh1XZ8M2qppbC5uNXFQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/core": ">=13.0.0" - } - }, - "node_modules/nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "!win32" - ], - "dependencies": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", - "dev": true, - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "dependencies": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-bundled": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", - "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", - "dev": true, - "dependencies": { - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", - "dev": true, - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", - "dev": true, - "dependencies": { - "ignore-walk": "^6.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-pick-manifest": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", - "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", - "dev": true, - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-registry-fetch": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", - "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", - "dev": true, - "dependencies": { - "make-fetch-happen": "^11.0.0", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-registry-fetch/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-registry-fetch/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm-registry-fetch/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.1.tgz", - "integrity": "sha512-/4b7qZNhv6Uhd7jjnREh1NjnPxlTq+XNWPG88Ydkj5AILcA5m3ajvcg57pB24EQjKv0dK62XnDqk9c/hkIG5Kg==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry/node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pacote": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.1.0.tgz", - "integrity": "sha512-FFcjtIl+BQNfeliSm7MZz5cpdohvUV1yjGnqgVM4UnVF7JslRY0ImXAygdaCDV0jjUADEWu4y5xsDV8brtrTLg==", - "dev": true, - "dependencies": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^4.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "devOptional": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-html-rewriting-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", - "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", - "dev": true, - "dependencies": { - "entities": "^4.3.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-sax-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", - "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", - "dev": true, - "dependencies": { - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "devOptional": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/piscina": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-3.2.0.tgz", - "integrity": "sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA==", - "dev": true, - "dependencies": { - "eventemitter-asyncresource": "^1.0.0", - "hdr-histogram-js": "^2.0.1", - "hdr-histogram-percentiles-obj": "^3.0.0" - }, - "optionalDependencies": { - "nice-napi": "^1.0.2" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-loader": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.0.2.tgz", - "integrity": "sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/preact": { - "version": "10.12.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz", - "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-java": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-1.6.2.tgz", - "integrity": "sha512-oVIUOkx50eb9skdRtEIU7MJUsizQ1ZocgXR1w1o8AnieNGpuPI/2pWnpjtbBm9wUG1dHtBGU8cVIr8h+xgzQIg==", - "dev": true, - "dependencies": { - "java-parser": "2.0.2", - "lodash": "4.17.21", - "prettier": "2.3.1" - } - }, - "node_modules/prettier-plugin-java/node_modules/prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-plugin-organize-imports": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz", - "integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==", - "dev": true, - "peerDependencies": { - "@volar/vue-language-plugin-pug": "^1.0.4", - "@volar/vue-typescript": "^1.0.4", - "prettier": ">=2.0", - "typescript": ">=2.9" - }, - "peerDependenciesMeta": { - "@volar/vue-language-plugin-pug": { - "optional": true - }, - "@volar/vue-typescript": { - "optional": true - } - } - }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true, - "engines": { - "node": ">=0.9" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ramda": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", - "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/read-package-json": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", - "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", - "dev": true, - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/read-package-json/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/read-package-json/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regex-parser": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", - "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", - "dev": true - }, - "node_modules/regexp-to-ast": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.4.0.tgz", - "integrity": "sha512-4qf/7IsIKfSNHQXSwial1IFmfM1Cc/whNBQqRwe0V2stPe7KmN1U0tWQiIx6JiirgSrisjE0eECdNf7Tav1Ntw==", - "dev": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", - "dev": true, - "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sass": { - "version": "1.58.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.1.tgz", - "integrity": "sha512-bnINi6nPXbP1XNRaranMFEBZWUfdW/AF16Ql5+ypRxfTvCRTTKrLsMIakyDcayUt2t/RZotmL4kgJwNH5xO+bg==", - "dev": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/sass-loader": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz", - "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==", - "dev": true, - "dependencies": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } - } - }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", - "dev": true, - "optional": true - }, - "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sigstore": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", - "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", - "dev": true, - "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "@sigstore/sign": "^1.0.0", - "@sigstore/tuf": "^1.0.3", - "make-fetch-happen": "^11.0.1" - }, - "bin": { - "sigstore": "bin/sigstore.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/sigstore/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/sigstore/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/sigstore/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sigstore/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/sigstore/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sirv": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", - "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.5.2", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", - "dev": true, - "dependencies": { - "ws": "~8.11.0" - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "dev": true, - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-loader": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", - "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.72.1" - } - }, - "node_modules/source-map-loader/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", - "dev": true - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/ssri/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/streamroller": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", - "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", - "dev": true, - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/terser": { - "version": "5.16.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", - "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/terser-webpack-plugin/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", - "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-toolbelt": { - "version": "6.15.5", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", - "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==", - "dev": true - }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tuf-js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", - "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", - "dev": true, - "dependencies": { - "@tufjs/models": "1.0.4", - "debug": "^4.3.4", - "make-fetch-happen": "^11.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/tuf-js/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/tuf-js/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/tuf-js/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/ua-parser-js": { - "version": "0.7.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", - "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "engines": { - "node": "*" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz", - "integrity": "sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "is-plain-object": "^5.0.0", - "lodash.debounce": "^4.0.8", - "lodash.escape": "^4.0.1", - "lodash.flatten": "^4.4.0", - "lodash.invokemap": "^4.6.0", - "lodash.pullall": "^4.2.0", - "lodash.uniqby": "^4.7.0", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-dev-middleware": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.0.1.tgz", - "integrity": "sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz", - "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-subresource-integrity": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", - "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", - "dev": true, - "dependencies": { - "typed-assert": "^1.0.8" - }, - "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", - "webpack": "^5.12.0" - }, - "peerDependenciesMeta": { - "html-webpack-plugin": { - "optional": true - } - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zone.js": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.8.tgz", - "integrity": "sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==", - "dependencies": { - "tslib": "^2.3.0" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@angular-devkit/architect": { - "version": "0.1502.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1502.10.tgz", - "integrity": "sha512-S8lN73WYCfpEpw1Q41ZcUinw7JfDeSM8LyGs797OVshnW75QcOkOecWj/3CKR23G44IgFrHN6sqtzWxKmMxLig==", - "dev": true, - "requires": { - "@angular-devkit/core": "15.2.10", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/build-angular": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-15.2.10.tgz", - "integrity": "sha512-3pCPVEJilVwHIJC6Su1/PIEqvFfU1Lxew9yItxX4s6dud8HY+fuKrsDnao4NNMFNqCLqL4el5QbSBKnnpWH1sg==", - "dev": true, - "requires": { - "@ampproject/remapping": "2.2.0", - "@angular-devkit/architect": "0.1502.10", - "@angular-devkit/build-webpack": "0.1502.10", - "@angular-devkit/core": "15.2.10", - "@babel/core": "7.20.12", - "@babel/generator": "7.20.14", - "@babel/helper-annotate-as-pure": "7.18.6", - "@babel/helper-split-export-declaration": "7.18.6", - "@babel/plugin-proposal-async-generator-functions": "7.20.7", - "@babel/plugin-transform-async-to-generator": "7.20.7", - "@babel/plugin-transform-runtime": "7.19.6", - "@babel/preset-env": "7.20.2", - "@babel/runtime": "7.20.13", - "@babel/template": "7.20.7", - "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "15.2.10", - "ansi-colors": "4.1.3", - "autoprefixer": "10.4.13", - "babel-loader": "9.1.2", - "babel-plugin-istanbul": "6.1.1", - "browserslist": "4.21.5", - "cacache": "17.0.4", - "chokidar": "3.5.3", - "copy-webpack-plugin": "11.0.0", - "critters": "0.0.16", - "css-loader": "6.7.3", - "esbuild": "0.17.8", - "esbuild-wasm": "0.17.8", - "glob": "8.1.0", - "https-proxy-agent": "5.0.1", - "inquirer": "8.2.4", - "jsonc-parser": "3.2.0", - "karma-source-map-support": "1.4.0", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "4.0.2", - "loader-utils": "3.2.1", - "magic-string": "0.29.0", - "mini-css-extract-plugin": "2.7.2", - "open": "8.4.1", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", - "piscina": "3.2.0", - "postcss": "8.4.31", - "postcss-loader": "7.0.2", - "resolve-url-loader": "5.0.0", - "rxjs": "6.6.7", - "sass": "1.58.1", - "sass-loader": "13.2.0", - "semver": "7.5.3", - "source-map-loader": "4.0.1", - "source-map-support": "0.5.21", - "terser": "5.16.3", - "text-table": "0.2.0", - "tree-kill": "1.2.2", - "tslib": "2.5.0", - "webpack": "5.76.1", - "webpack-dev-middleware": "6.0.1", - "webpack-dev-server": "4.11.1", - "webpack-merge": "5.8.0", - "webpack-subresource-integrity": "5.1.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "webpack": { - "version": "5.76.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", - "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - } - } - } - }, - "@angular-devkit/build-webpack": { - "version": "0.1502.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1502.10.tgz", - "integrity": "sha512-55b9WZIGU4DNgiIV2lkkN6iQxJrgWY5CDaNu0kJC/qazotJgBbcN/8jgBx2DD8HNE1V3iXxWk66pt1h946Po+Q==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.1502.10", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/core": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.10.tgz", - "integrity": "sha512-bFPm7wjvfBds9km2rCJxUhzkqe4h3h/199yJtzC1bNvwRr2LMHvtyoQAzftda+gs7Ulqac5wzUEZX/cVV3WrsA==", - "dev": true, - "requires": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "6.6.7", - "source-map": "0.7.4" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-15.2.10.tgz", - "integrity": "sha512-EeoDs4oKFpLZNa21G/8dqBdclEc4U2piI9EeXCVTaN6z5DYXIZ0G1WtCXU8nhD+GckS47rmfZ4/3lMaXAvED+g==", - "dev": true, - "requires": { - "@angular-devkit/core": "15.2.10", - "jsonc-parser": "3.2.0", - "magic-string": "0.29.0", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-eslint/builder": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-15.2.1.tgz", - "integrity": "sha512-7x2DANebLRl997Mj4DhZrnz5+vnSjavGGveJ0mBuU7CEsL0ZYLftdRqL0e0HtU3ksseS7xpchD6OM08nkNgySw==", - "dev": true, - "requires": {} - }, - "@angular-eslint/bundled-angular-compiler": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-15.2.1.tgz", - "integrity": "sha512-LO7Am8eVCr7oh6a0VmKSL7K03CnQEQhFO7Wt/YtbfYOxVjrbwmYLwJn+wZPOT7A02t/BttOD/WXuDrOWtSMQ/Q==", - "dev": true - }, - "@angular-eslint/eslint-plugin": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-15.2.1.tgz", - "integrity": "sha512-OM7b1kS4E4CkXjkaWN+lEzawh4VxY6l7FO1Cuk4s7iv3/YpZG3rJxIZBqnFLTixwrBuqw8y4FNBzF3eDgmFAUw==", - "dev": true, - "requires": { - "@angular-eslint/utils": "15.2.1", - "@typescript-eslint/utils": "5.48.2" - } - }, - "@angular-eslint/eslint-plugin-template": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-15.2.1.tgz", - "integrity": "sha512-IeiSLk6YxapFdH2z5o/O3R7VwtBd2T6fWmhLFPwDYMDknrwegnOjwswCdBplOccpUp0wqlCeGUx7LTsuzwaz7w==", - "dev": true, - "requires": { - "@angular-eslint/bundled-angular-compiler": "15.2.1", - "@angular-eslint/utils": "15.2.1", - "@typescript-eslint/type-utils": "5.48.2", - "@typescript-eslint/utils": "5.48.2", - "aria-query": "5.1.3", - "axobject-query": "3.1.1" - } - }, - "@angular-eslint/schematics": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-15.2.1.tgz", - "integrity": "sha512-0ZfBCejHWIcgy3J5kFs9sS/jqi8i5AptxggOwFySOlCLJ+CzNrktjD4jff1Zy8K/VLzY0Ci0BSZXvgWfP0k9Rg==", - "dev": true, - "requires": { - "@angular-eslint/eslint-plugin": "15.2.1", - "@angular-eslint/eslint-plugin-template": "15.2.1", - "ignore": "5.2.4", - "strip-json-comments": "3.1.1", - "tmp": "0.2.1" - } - }, - "@angular-eslint/template-parser": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-15.2.1.tgz", - "integrity": "sha512-ViCi79gC2aKJecmYLkOT+QlT5WMRNXeYz0Dr9Pr8qXzIbY0oAWE7nOT5jkXwQ9oUk+ybtGCWHma5JVJWVJsIog==", - "dev": true, - "requires": { - "@angular-eslint/bundled-angular-compiler": "15.2.1", - "eslint-scope": "^7.0.0" - } - }, - "@angular-eslint/utils": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-15.2.1.tgz", - "integrity": "sha512-++FneAJHxJqcSu0igVN6uOkSoHxlzgLoMBswuovYJy3UKwm33/T6WFku8++753Ca/JucIoR1gdUfO7SoSspMDg==", - "dev": true, - "requires": { - "@angular-eslint/bundled-angular-compiler": "15.2.1", - "@typescript-eslint/utils": "5.48.2" - } - }, - "@angular/animations": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-15.2.10.tgz", - "integrity": "sha512-yxfN8qQpMaukRU5LjFkJBmy85rqrOp86tYVCsf+hmPEFRiXBMUj6xYLeCMcpk3Mt1JtnWGBR34ivGx+7bNeAow==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/cdk": { - "version": "15.2.9", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-15.2.9.tgz", - "integrity": "sha512-koaM07N1AIQ5oHU27l0/FoQSSoYAwlAYwVZ4Di3bYrJsTBNCN2Xsby7wI8gZxdepMnV4Fe9si382BDBov+oO4Q==", - "requires": { - "parse5": "^7.1.2", - "tslib": "^2.3.0" - } - }, - "@angular/cli": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-15.2.10.tgz", - "integrity": "sha512-/TSnm/ZQML6A4lvunyN2tjTB5utuvk3d1Pnfyehp/FXtV6YfZm6+EZrOpKkKPCxTuAgW6c9KK4yQtt3RuNVpwQ==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.1502.10", - "@angular-devkit/core": "15.2.10", - "@angular-devkit/schematics": "15.2.10", - "@schematics/angular": "15.2.10", - "@yarnpkg/lockfile": "1.1.0", - "ansi-colors": "4.1.3", - "ini": "3.0.1", - "inquirer": "8.2.4", - "jsonc-parser": "3.2.0", - "npm-package-arg": "10.1.0", - "npm-pick-manifest": "8.0.1", - "open": "8.4.1", - "ora": "5.4.1", - "pacote": "15.1.0", - "resolve": "1.22.1", - "semver": "7.5.3", - "symbol-observable": "4.0.0", - "yargs": "17.6.2" - } - }, - "@angular/common": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-15.2.10.tgz", - "integrity": "sha512-jdBn3fctkqoNrJn9VLsUHpcCEhCxWSczdsR+BBbD6T0oLl6vMrAVNjPwfBejnlgfWN1KoRU9kgOYsMxa5apIWQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/compiler": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-15.2.10.tgz", - "integrity": "sha512-M0XkeU0O73UlJZwDvOyp8/apetz9UKj78eTFDseMYJDLcxe6MpkbkxqpsGZnKYDj7LIep8PmCAKEkhtenE82zw==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/compiler-cli": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-15.2.10.tgz", - "integrity": "sha512-mCFIxrs60XicKfA2o42hA7LrQvhybi9BQveWuZn/2iIEOXx7R62Iemz8E21pLWftAZHGxEW3NECfBrY1d3gVmA==", - "requires": { - "@babel/core": "7.19.3", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^3.0.0", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.11.0", - "magic-string": "^0.27.0", - "reflect-metadata": "^0.1.2", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^17.2.1" - }, - "dependencies": { - "@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.13" - } - } - } - }, - "@angular/core": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-15.2.10.tgz", - "integrity": "sha512-meGGidnitQJGDxYd9/LrqYiVlId+vGaLoiLgJdKBz+o2ZO6OmXQGuNw2VBqf17/Cc0/UjzrOY7+kILNFKkk/WQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/forms": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-15.2.10.tgz", - "integrity": "sha512-NIntGsNcN6o8L1txsbWXOf6f3K/CUBizdKsxsYVYGJIXEW5qU6UnWmfAZffNNXsT/XvbgUCjgDwT0cAwcqZPuQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/localize": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-15.2.10.tgz", - "integrity": "sha512-RHN+mUR4H34c/LLnNPAyQbfuZME4i9JgodK5YRRX8cSAFPafYLT0SspSuLsKtcCCEDadAZNDHzb8qv5MBtzJtg==", - "requires": { - "@babel/core": "7.19.3", - "glob": "8.1.0", - "yargs": "^17.2.1" - }, - "dependencies": { - "@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@angular/platform-browser": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.10.tgz", - "integrity": "sha512-9tbgVGSJqwfrOzT8aA/kWBLNhJSQ9gUg0CJxwFBSJm8VkBUJrszoBlDsnSvlxx8/W2ejNULKHFTXeUzq0O/+RQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/platform-browser-dynamic": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.10.tgz", - "integrity": "sha512-JHP6W+FX715Qv7DhqvfZLuBZXSDJrboiQsR06gUAgDSjAUyhbqmpVg/2YOtgeWpPkzNDtXdPU2PhcRdIv5J3Yg==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/router": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-15.2.10.tgz", - "integrity": "sha512-LmuqEg0iIXSw7bli6HKJ19cbxP91v37GtRwbGKswyLihqzTgvjBYpvcfMnB5FRQ5LWkTwq5JclkX03dZw290Yg==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@assemblyscript/loader": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", - "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", - "dev": true - }, - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - } - }, - "@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==" - }, - "@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/generator": { - "version": "7.20.14", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", - "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", - "requires": { - "@babel/types": "^7.20.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.15" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", - "requires": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "dependencies": { - "browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "requires": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", - "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" - }, - "dependencies": { - "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "dependencies": { - "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "dependencies": { - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - } - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "requires": { - "@babel/types": "^7.22.15" - } - }, - "@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "dependencies": { - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "requires": { - "@babel/types": "^7.22.5" - } - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" - }, - "dependencies": { - "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - } - } - }, - "@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" - } - }, - "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" - }, - "@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==" - }, - "@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" - }, - "dependencies": { - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - } - } - }, - "@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", - "requires": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" - }, - "dependencies": { - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - } - } - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", - "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", - "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.15" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", - "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", - "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", - "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" - }, - "dependencies": { - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - } - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", - "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", - "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", - "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", - "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", - "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", - "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", - "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", - "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", - "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", - "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" - } - }, - "@babel/plugin-transform-optional-chaining": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", - "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", - "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", - "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "regenerator-transform": "^0.15.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", - "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz", - "integrity": "sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", - "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", - "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", - "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", - "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/preset-modules": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", - "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "@babel/runtime": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", - "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.11" - } - }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@esbuild/android-arm": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz", - "integrity": "sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz", - "integrity": "sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz", - "integrity": "sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz", - "integrity": "sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz", - "integrity": "sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz", - "integrity": "sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz", - "integrity": "sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz", - "integrity": "sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz", - "integrity": "sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz", - "integrity": "sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz", - "integrity": "sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz", - "integrity": "sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz", - "integrity": "sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz", - "integrity": "sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz", - "integrity": "sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz", - "integrity": "sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz", - "integrity": "sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz", - "integrity": "sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz", - "integrity": "sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz", - "integrity": "sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz", - "integrity": "sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz", - "integrity": "sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==", - "dev": true, - "optional": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", - "dev": true - }, - "@fullcalendar/angular": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.9.tgz", - "integrity": "sha512-cN91zGQEGM9s6VnD+2jNdHomAGHJIGSMBR0ts5gJC0FIRCuLtjDxiZN4kNfRWxx7NJiSLm+NCKijo6317pGhsw==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@fullcalendar/core": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.9.tgz", - "integrity": "sha512-eeG+z9BWerdsU9Ac6j16rpYpPnE0wxtnEHiHrh/u/ADbGTR3hCOjCD9PxQOfhOTHbWOVs7JQunGcksSPu5WZBQ==", - "peer": true, - "requires": { - "preact": "~10.12.1" - } - }, - "@fullcalendar/daygrid": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.9.tgz", - "integrity": "sha512-o/6joH/7lmVHXAkbaa/tUbzWYnGp/LgfdiFyYPkqQbjKEeivNZWF1WhHqFbhx0zbFONSHtrvkjY2bjr+Ef2quQ==", - "requires": {} - }, - "@fullcalendar/luxon2": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/luxon2/-/luxon2-6.1.9.tgz", - "integrity": "sha512-HbHbk+iwBv0PpM8WPA3U6mI0OTSfTMSD31+3PlKh3/YKjpYnG6ITzoh1yjS4Fg1Yas/t6OCQHCuW02st0HUEJQ==", - "requires": {} - }, - "@fullcalendar/timegrid": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.9.tgz", - "integrity": "sha512-le7UV05wVE1Trdr054kgJXTwa+A1pEI8nlCBnPWdcyrL+dTLoPvQ4AWEVCnV7So+4zRYaCqnqGXfCJsj0RQa0g==", - "requires": { - "@fullcalendar/daygrid": "~6.1.9" - } - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" - }, - "@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "@ng-bootstrap/ng-bootstrap": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-14.2.0.tgz", - "integrity": "sha512-nqEKVXauSontGKqC5WSKpch5TiAGDZB3hluvxkINS0r9LUE6sBQRP3qeYOe7Uwu+UbQcj28NG3qFHhpfnG8KHw==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@ngtools/webpack": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.10.tgz", - "integrity": "sha512-ZExB4rKh/Saad31O/Ofd2XvRuILuCNTYs0+qJL697Be2pzeewvzBhE4Xe1Mm7Jg13aWSPeuIdzSGOqCdwxxxFQ==", - "dev": true, - "requires": {} - }, - "@ngx-translate/core": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", - "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@ngx-translate/http-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz", - "integrity": "sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "requires": { - "semver": "^7.3.5" - } - }, - "@npmcli/git": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", - "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", - "dev": true, - "requires": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", - "dev": true - }, - "@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", - "dev": true, - "requires": { - "which": "^3.0.0" - }, - "dependencies": { - "which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@npmcli/run-script": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", - "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" - }, - "dependencies": { - "which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@polka/url": { - "version": "1.0.0-next.23", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", - "dev": true - }, - "@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" - }, - "@schematics/angular": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-15.2.10.tgz", - "integrity": "sha512-eLdyP+T1TueNQ8FCP7sP+tt8z+YQ1BINsJsyAyoJT/XZjcCV7LUxgDIU94/kuvIotmJ2xTuFWHFPfAY+CN3duQ==", - "dev": true, - "requires": { - "@angular-devkit/core": "15.2.10", - "@angular-devkit/schematics": "15.2.10", - "jsonc-parser": "3.2.0" - } - }, - "@sigstore/bundle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", - "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", - "dev": true, - "requires": { - "@sigstore/protobuf-specs": "^0.2.0" - } - }, - "@sigstore/protobuf-specs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", - "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", - "dev": true - }, - "@sigstore/sign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", - "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", - "dev": true, - "requires": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "make-fetch-happen": "^11.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - } - } - }, - "@sigstore/tuf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", - "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", - "dev": true, - "requires": { - "@sigstore/protobuf-specs": "^0.2.0", - "tuf-js": "^1.1.7" - } - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", - "dev": true - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@tufjs/canonical-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", - "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", - "dev": true - }, - "@tufjs/models": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", - "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", - "dev": true, - "requires": { - "@tufjs/canonical-json": "1.0.0", - "minimatch": "^9.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@types/body-parser": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", - "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", - "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ckeditor": { - "version": "4.9.10", - "resolved": "https://registry.npmjs.org/@types/ckeditor/-/ckeditor-4.9.10.tgz", - "integrity": "sha512-dcOPCXM0Cr5Z0i6eF/aW5LvECrS+cdl2Gi7lU+rEUNWby0w9Yl6mBubjrs29OVAducpuZjB4mfDayE+o4/gGdQ==", - "dev": true - }, - "@types/connect": { - "version": "3.4.37", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", - "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", - "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true - }, - "@types/cors": { - "version": "2.8.15", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.15.tgz", - "integrity": "sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.44.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", - "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", - "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", - "dev": true - }, - "@types/express": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", - "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.39", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", - "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "@types/file-saver-es": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/file-saver-es/-/file-saver-es-2.0.2.tgz", - "integrity": "sha512-f9S7EJ0wHHpomR5EhQt4w6hYrewSOjdvTvPxDDZPPdB7CTrjyRHxx4htbIHkGN7CVe3j9nJaJ9d2VIZr3QZUTQ==", - "dev": true - }, - "@types/http-errors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", - "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.13", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", - "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/jasmine": { - "version": "3.10.15", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.15.tgz", - "integrity": "sha512-NdWern4OhbU7QcdlpPnvqy7LqpEjiAQ47tHDRdUKyGcwnhdmTsGniSJCC2B9ODiYiRnP53v6HOzu8B5/bqOtUw==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", - "dev": true - }, - "@types/luxon": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.3.tgz", - "integrity": "sha512-/BJF3NT0pRMuxrenr42emRUF67sXwcZCd+S1ksG/Fcf9O7C3kKCY4uJSbKBE4KDUIYr3WMsvfmWD8hRjXExBJQ==", - "dev": true - }, - "@types/mathjax": { - "version": "0.0.37", - "resolved": "https://registry.npmjs.org/@types/mathjax/-/mathjax-0.0.37.tgz", - "integrity": "sha512-y0WSZBtBNQwcYipTU/BhgeFu1EZNlFvUNCmkMXV9kBQZq7/o5z82dNVyH3yy2Xv5zzeNeQoHSL4Xm06+EQiH+g==", - "dev": true - }, - "@types/mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", - "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", - "dev": true - }, - "@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", - "dev": true, - "requires": { - "undici-types": "~5.26.4" - } - }, - "@types/node-forge": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", - "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/parse-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", - "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==", - "dev": true - }, - "@types/qs": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", - "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", - "dev": true - }, - "@types/ramda": { - "version": "0.28.25", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.25.tgz", - "integrity": "sha512-HrQNqQAGcITpn9HAJFamDxm7iZeeXiP/95pN5OMbNniDjzCCeOHbBKNGmUy8NRi0fhYS+/cXeo91MFC+06gbow==", - "dev": true, - "requires": { - "ts-toolbelt": "^6.15.1" - } - }, - "@types/range-parser": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", - "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", - "dev": true - }, - "@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", - "dev": true - }, - "@types/send": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", - "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/serve-index": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", - "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", - "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", - "dev": true, - "requires": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.35", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", - "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", - "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.2.tgz", - "integrity": "sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.48.2", - "@typescript-eslint/utils": "5.48.2", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", - "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", - "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/visitor-keys": "5.48.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", - "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.2", - "eslint-visitor-keys": "^3.3.0" - } - } - } - }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.2.tgz", - "integrity": "sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.48.2", - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/typescript-estree": "5.48.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", - "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/visitor-keys": "5.48.2" - } - }, - "@typescript-eslint/types": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", - "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", - "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.2", - "@typescript-eslint/visitor-keys": "5.48.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.48.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", - "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", - "dev": true - }, - "adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dev": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, - "babel-loader": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.2.tgz", - "integrity": "sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==", - "dev": true, - "requires": { - "find-cache-dir": "^3.3.2", - "schema-utils": "^4.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, - "requires": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "bootstrap": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", - "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", - "requires": {} - }, - "bootstrap-icons": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.1.tgz", - "integrity": "sha512-F0DDp7nKUX+x/QtpfRZ+XHFya60ng9nfdpdS59vDDfs4Uhuxp7zym/QavMsu/xx51txkoM9eVmpE7D08N35blw==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "cacache": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz", - "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==", - "dev": true, - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^8.0.1", - "lru-cache": "^7.7.1", - "minipass": "^4.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, - "call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "requires": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chart.js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz", - "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==" - }, - "chartjs-plugin-datalabels": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz", - "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==", - "requires": {} - }, - "chevrotain": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-6.5.0.tgz", - "integrity": "sha512-BwqQ/AgmKJ8jcMEjaSnfMybnKMgGTrtDKowfTP3pX4jwVy0kNjRsT/AP6h+wC3+3NC+X8X15VWBnTCQlX+wQFg==", - "dev": true, - "requires": { - "regexp-to-ast": "0.4.0" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", - "dev": true - }, - "cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "commander": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", - "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "requires": { - "is-what": "^3.14.1" - } - }, - "copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", - "dev": true, - "requires": { - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.1", - "globby": "^13.1.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dev": true, - "requires": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - } - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true - } - } - }, - "core-js-compat": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", - "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", - "dev": true, - "requires": { - "browserslist": "^4.22.1" - }, - "dependencies": { - "browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" - } - } - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "dependencies": { - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - } - } - }, - "critters": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.16.tgz", - "integrity": "sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "css-select": "^4.2.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "postcss": "^8.3.7", - "pretty-bytes": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-loader": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", - "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.19", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - } - }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", - "dev": true - }, - "date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "requires": { - "@babel/runtime": "^7.21.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", - "requires": { - "regenerator-runtime": "^0.14.0" - } - }, - "regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" - } - } - }, - "date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - } - } - }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.569", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", - "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "engine.io": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", - "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", - "dev": true, - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" - } - }, - "engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", - "dev": true - }, - "enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", - "dev": true - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - } - }, - "es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", - "dev": true - }, - "esbuild": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz", - "integrity": "sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==", - "dev": true, - "optional": true, - "requires": { - "@esbuild/android-arm": "0.17.8", - "@esbuild/android-arm64": "0.17.8", - "@esbuild/android-x64": "0.17.8", - "@esbuild/darwin-arm64": "0.17.8", - "@esbuild/darwin-x64": "0.17.8", - "@esbuild/freebsd-arm64": "0.17.8", - "@esbuild/freebsd-x64": "0.17.8", - "@esbuild/linux-arm": "0.17.8", - "@esbuild/linux-arm64": "0.17.8", - "@esbuild/linux-ia32": "0.17.8", - "@esbuild/linux-loong64": "0.17.8", - "@esbuild/linux-mips64el": "0.17.8", - "@esbuild/linux-ppc64": "0.17.8", - "@esbuild/linux-riscv64": "0.17.8", - "@esbuild/linux-s390x": "0.17.8", - "@esbuild/linux-x64": "0.17.8", - "@esbuild/netbsd-x64": "0.17.8", - "@esbuild/openbsd-x64": "0.17.8", - "@esbuild/sunos-x64": "0.17.8", - "@esbuild/win32-arm64": "0.17.8", - "@esbuild/win32-ia32": "0.17.8", - "@esbuild/win32-x64": "0.17.8" - } - }, - "esbuild-wasm": { - "version": "0.17.8", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.17.8.tgz", - "integrity": "sha512-zCmpxv95E0FuCmvdw1K836UHnj4EdiQnFfjTby35y3LAjRPtXMj3sbHDRHjbD8Mqg5lTwq3knacr/1qIFU51CQ==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true - }, - "eventemitter-asyncresource": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", - "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - } - }, - "exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-saver-es": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/file-saver-es/-/file-saver-es-2.0.5.tgz", - "integrity": "sha512-Kg0lt+is9nOyi/VDms9miScNGot25jVFbjFccXuCL/shd2Q+rt70MALxHVkXllsX83JEBLiHQNjDPGd/6FIOoQ==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - } - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - }, - "fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "optional": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "requires": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "requires": { - "duplexer": "^0.1.2" - } - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.2" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dev": true, - "requires": { - "function-bind": "^1.1.2" - } - }, - "hdr-histogram-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", - "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", - "dev": true, - "requires": { - "@assemblyscript/loader": "^0.10.1", - "base64-js": "^1.2.0", - "pako": "^1.0.3" - } - }, - "hdr-histogram-percentiles-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", - "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", - "dev": true - }, - "hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "ignore-walk": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", - "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", - "dev": true, - "requires": { - "minimatch": "^9.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true - }, - "immutable": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", - "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", - "dev": true - }, - "inquirer": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", - "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, - "ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "requires": { - "which-typed-array": "^1.1.11" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "requires": { - "semver": "^7.5.3" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jasmine-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", - "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", - "dev": true - }, - "java-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-2.0.2.tgz", - "integrity": "sha512-fwv1eDYE4OIAN+XS7cD8aB7UdQyAh3Uz36ydWqemvnDKXEdLbxq7qIbvsjpSvS1NHFR+r81N7AjGcpnamjVxJw==", - "dev": true, - "requires": { - "chevrotain": "6.5.0", - "lodash": "4.17.21" - } - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true - }, - "karma": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", - "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "dependencies": { - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } - } - }, - "karma-chrome-launcher": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", - "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", - "dev": true, - "requires": { - "which": "^1.2.1" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "karma-coverage": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", - "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - } - }, - "karma-jasmine": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.2.tgz", - "integrity": "sha512-ggi84RMNQffSDmWSyyt4zxzh2CQGwsxvYYsprgyR1j8ikzIduEdOlcLvXjZGwXG/0j41KUXOWsUCBfbEHPWP9g==", - "dev": true, - "requires": { - "jasmine-core": "^3.6.0" - }, - "dependencies": { - "jasmine-core": { - "version": "3.99.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", - "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", - "dev": true - } - } - }, - "karma-jasmine-html-reporter": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", - "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", - "dev": true, - "requires": {} - }, - "karma-source-map-support": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", - "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", - "dev": true, - "requires": { - "source-map-support": "^0.5.5" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true - }, - "less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", - "dev": true, - "requires": { - "copy-anything": "^2.0.1", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "parse-node-version": "^1.0.1", - "source-map": "~0.6.0", - "tslib": "^2.3.0" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, - "less-loader": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", - "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", - "dev": true, - "requires": { - "klona": "^2.0.4" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "license-webpack-plugin": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", - "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", - "dev": true, - "requires": { - "webpack-sources": "^3.0.0" - } - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "lint-staged": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz", - "integrity": "sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ==", - "dev": true, - "requires": { - "chalk": "5.3.0", - "commander": "11.0.0", - "debug": "4.3.4", - "execa": "7.2.0", - "lilconfig": "2.1.0", - "listr2": "6.6.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.1" - }, - "dependencies": { - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - } - } - }, - "listr2": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", - "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", - "dev": true, - "requires": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", - "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, - "lodash.invokemap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz", - "integrity": "sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.pullall": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.pullall/-/lodash.pullall-4.2.0.tgz", - "integrity": "sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg==", - "dev": true - }, - "lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", - "dev": true, - "requires": { - "ansi-escapes": "^5.0.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" - }, - "dependencies": { - "ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", - "dev": true, - "requires": { - "type-fest": "^1.0.2" - } - }, - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "requires": { - "restore-cursor": "^4.0.0" - } - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "luxon": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz", - "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==" - }, - "magic-string": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", - "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.13" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "requires": { - "unique-slug": "^3.0.0" - } - }, - "unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.4" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", - "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", - "dev": true, - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "needle": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", - "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "ngx-toastr": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-16.2.0.tgz", - "integrity": "sha512-7X6UhOKiaUeC2eTOsUqctZH0ZWKG8VlzDxWJhdEF1N3kPod46SU/Vn2l0hbt8EDwTjxHKfKyevU2idkYDoZYog==", - "requires": { - "tslib": "^2.3.0" - } - }, - "ngx-webstorage-service": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ngx-webstorage-service/-/ngx-webstorage-service-5.0.0.tgz", - "integrity": "sha512-adipYzdVGA1HxPF5n62eJoQGohiJRlpCp7lPuNQcOvkHGfFUByAfXZHmmLFzb5OFfeNWh1XZ8M2qppbC5uNXFQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "optional": true, - "requires": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", - "dev": true, - "optional": true - }, - "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "npm-bundled": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", - "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^3.0.0" - } - }, - "npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true - }, - "npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "requires": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", - "dev": true, - "requires": { - "ignore-walk": "^6.0.0" - } - }, - "npm-pick-manifest": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", - "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", - "dev": true, - "requires": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - } - }, - "npm-registry-fetch": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", - "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", - "dev": true, - "requires": { - "make-fetch-happen": "^11.0.0", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - } - } - }, - "npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true - }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "open": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.1.tgz", - "integrity": "sha512-/4b7qZNhv6Uhd7jjnREh1NjnPxlTq+XNWPG88Ydkj5AILcA5m3ajvcg57pB24EQjKv0dK62XnDqk9c/hkIG5Kg==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "dependencies": { - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - } - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pacote": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.1.0.tgz", - "integrity": "sha512-FFcjtIl+BQNfeliSm7MZz5cpdohvUV1yjGnqgVM4UnVF7JslRY0ImXAygdaCDV0jjUADEWu4y5xsDV8brtrTLg==", - "dev": true, - "requires": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^4.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - } - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "devOptional": true, - "requires": { - "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "devOptional": true - } - } - }, - "parse5-html-rewriting-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", - "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", - "dev": true, - "requires": { - "entities": "^4.3.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - } - } - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - }, - "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - } - } - }, - "parse5-sax-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", - "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", - "dev": true, - "requires": { - "parse5": "^7.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", - "dev": true - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true - }, - "piscina": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-3.2.0.tgz", - "integrity": "sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA==", - "dev": true, - "requires": { - "eventemitter-asyncresource": "^1.0.0", - "hdr-histogram-js": "^2.0.1", - "hdr-histogram-percentiles-obj": "^3.0.0", - "nice-napi": "^1.0.2" - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-loader": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.0.2.tgz", - "integrity": "sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.8" - } - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "preact": { - "version": "10.12.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz", - "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==", - "peer": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, - "prettier-plugin-java": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-1.6.2.tgz", - "integrity": "sha512-oVIUOkx50eb9skdRtEIU7MJUsizQ1ZocgXR1w1o8AnieNGpuPI/2pWnpjtbBm9wUG1dHtBGU8cVIr8h+xgzQIg==", - "dev": true, - "requires": { - "java-parser": "2.0.2", - "lodash": "4.17.21", - "prettier": "2.3.1" - }, - "dependencies": { - "prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", - "dev": true - } - } - }, - "prettier-plugin-organize-imports": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz", - "integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==", - "dev": true, - "requires": {} - }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "ramda": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", - "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "read-package-json": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", - "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", - "dev": true, - "requires": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", - "dev": true - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - }, - "read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-parser": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", - "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", - "dev": true - }, - "regexp-to-ast": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.4.0.tgz", - "integrity": "sha512-4qf/7IsIKfSNHQXSwial1IFmfM1Cc/whNBQqRwe0V2stPe7KmN1U0tWQiIx6JiirgSrisjE0eECdNf7Tav1Ntw==", - "dev": true - }, - "regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - } - }, - "regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "requires": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - } - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", - "dev": true, - "requires": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - } - } - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sass": { - "version": "1.58.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.1.tgz", - "integrity": "sha512-bnINi6nPXbP1XNRaranMFEBZWUfdW/AF16Ql5+ypRxfTvCRTTKrLsMIakyDcayUt2t/RZotmL4kgJwNH5xO+bg==", - "dev": true, - "requires": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - } - }, - "sass-loader": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz", - "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==", - "dev": true, - "requires": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - } - }, - "sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", - "dev": true, - "optional": true - }, - "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "requires": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - } - }, - "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "requires": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - } - }, - "set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sigstore": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", - "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", - "dev": true, - "requires": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "@sigstore/sign": "^1.0.0", - "@sigstore/tuf": "^1.0.3", - "make-fetch-happen": "^11.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - } - } - }, - "sirv": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", - "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", - "totalist": "^3.0.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - } - } - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, - "socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.5.2", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - } - }, - "socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", - "dev": true, - "requires": { - "ws": "~8.11.0" - } - }, - "socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "dev": true, - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - } - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "source-map-loader": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", - "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true - }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, - "streamroller": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", - "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - } - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - } - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "terser": { - "version": "5.16.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", - "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "terser": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", - "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "ts-toolbelt": { - "version": "6.15.5", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", - "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==", - "dev": true - }, - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tuf-js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", - "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", - "dev": true, - "requires": { - "@tufjs/models": "1.0.4", - "debug": "^4.3.4", - "make-fetch-happen": "^11.1.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - } - } - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true - }, - "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" - }, - "ua-parser-js": { - "version": "0.7.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", - "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", - "dev": true - }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", - "dev": true - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-bundle-analyzer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz", - "integrity": "sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "is-plain-object": "^5.0.0", - "lodash.debounce": "^4.0.8", - "lodash.escape": "^4.0.1", - "lodash.flatten": "^4.4.0", - "lodash.invokemap": "^4.6.0", - "lodash.pullall": "^4.2.0", - "lodash.uniqby": "^4.7.0", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "requires": {} - } - } - }, - "webpack-dev-middleware": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.0.1.tgz", - "integrity": "sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - } - }, - "webpack-dev-server": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz", - "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "dependencies": { - "webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - } - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "webpack-subresource-integrity": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", - "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", - "dev": true, - "requires": { - "typed-assert": "^1.0.8" - } - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - } - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "dev": true, - "requires": {} - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true - }, - "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "requires": { - "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-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - }, - "zone.js": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.8.tgz", - "integrity": "sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==", - "requires": { - "tslib": "^2.3.0" - } - } - } -} diff --git a/ui/package.json b/ui/package.json deleted file mode 100644 index 5cfcafb532..0000000000 --- a/ui/package.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "name": "exam", - "version": "6.2.3", - "description": "EXAM – electronic exam software for higher education", - "repository": { - "type": "git", - "url": " https://github.com/CSCfi/exam.git" - }, - "license": "EUPL-1.1", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build --build-optimizer false --output-path ../public", - "analyze": "ng build --stats-json && webpack-bundle-analyzer dist/exam/stats.json", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "ng lint --fix", - "format": "prettier --write \"src/app/**/*.{ts,html}\" --write \"../app/**/*.java\" --print-width=120 --tab-width=4; exit 0", - "prepare": "cd .. && npx husky install ui/.husky", - "check-format": "prettier --check \"src/app/**/*.{ts,html}\" --check \"../app/**/*.java\" --print-width=120 --tab-width=4; exit 0", - "check-lint": "ng lint" - }, - "dependencies": { - "@angular/animations": "^15.1.5", - "@angular/cdk": "^15.1.5", - "@angular/common": "^15.1.5", - "@angular/compiler": "^15.1.5", - "@angular/core": "^15.1.5", - "@angular/forms": "^15.1.5", - "@angular/localize": "^15.1.5", - "@angular/platform-browser": "^15.1.5", - "@angular/platform-browser-dynamic": "^15.1.5", - "@angular/router": "^15.1.5", - "@fullcalendar/angular": "^6.0.3", - "@fullcalendar/luxon2": "^6.0.3", - "@fullcalendar/timegrid": "^6.0.3", - "@ng-bootstrap/ng-bootstrap": "^14.0.1", - "@ngx-translate/core": "^14.0.0", - "@ngx-translate/http-loader": "^7.0.0", - "@popperjs/core": "^2.10.2", - "bootstrap": "~5.2.0", - "bootstrap-icons": "^1.3.0", - "chart.js": "^3.8.0", - "chartjs-plugin-datalabels": "^2.0.0", - "date-fns": "^2.25.0", - "file-saver-es": "^2.0.5", - "luxon": "^2.0.0", - "ngx-toastr": "^16.0.2", - "ngx-webstorage-service": "^5.0.0", - "ramda": "^0.28.0", - "rxjs": "^7.4.0", - "zone.js": "^0.11.4" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^15.1.6", - "@angular-eslint/builder": "^15.2.1", - "@angular-eslint/eslint-plugin": "^15.2.1", - "@angular-eslint/eslint-plugin-template": "^15.2.1", - "@angular-eslint/schematics": "^15.2.1", - "@angular-eslint/template-parser": "^15.2.1", - "@angular/cli": "^15.1.6", - "@angular/compiler-cli": "^15.1.5", - "@types/ckeditor": "^4.9.10", - "@types/file-saver-es": "^2.0.1", - "@types/jasmine": "^3.10.0", - "@types/luxon": "^3.1.0", - "@types/mathjax": "^0.0.37", - "@types/ramda": "^0.28.14", - "@typescript-eslint/eslint-plugin": "^5.43.0", - "@typescript-eslint/parser": "^5.43.0", - "eslint": "^8.28.0", - "husky": "^8.0.1", - "jasmine-core": "^4.0.0", - "karma": "^6.3.0", - "karma-chrome-launcher": "^3.1.0", - "karma-coverage": "^2.1.0", - "karma-jasmine": "^4.0.0", - "karma-jasmine-html-reporter": "^1.7.0", - "lint-staged": "^13.0.3", - "prettier": "^2.6.1", - "prettier-plugin-java": "^1.6.1", - "prettier-plugin-organize-imports": "^3.0.0", - "typescript": "~4.9.5", - "webpack": "^5.76.0", - "webpack-bundle-analyzer": "^4.5.0" - }, - "lint-staged": { - "src/app/**/*.{ts,html}": [ - "prettier --write" - ], - "../app/**/*.java": [ - "prettier --write --print-width=120 --tab-width=4" - ], - "../test/**/*.java": [ - "prettier --write --print-width=120 --tab-width=4" - ], - "src/app/**/*.ts": [ - "eslint --fix" - ] - } -} diff --git a/ui/src/app/administrative/administrative.module.ts b/ui/src/app/administrative/administrative.module.ts deleted file mode 100644 index a7863ab870..0000000000 --- a/ui/src/app/administrative/administrative.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateModule } from '@ngx-translate/core'; -import { SessionModule } from '../session/session.module'; -import { SharedModule } from '../shared/shared.module'; -import { ReportsModule } from './reports/reports.module'; -import { SettingsComponent } from './settings/settings.component'; -import { SettingsService } from './settings/settings.service'; -import { ExamStatisticsComponent } from './statistics/categories/exam-statistics.component'; -import { ReservationStatisticsComponent } from './statistics/categories/reservation-statistics.component'; -import { ResponseStatisticsComponent } from './statistics/categories/response-statistics.component'; -import { RoomStatisticsComponent } from './statistics/categories/room-statistics.component'; -import { StatisticsComponent } from './statistics/statistics.component'; -import { StatisticsService } from './statistics/statistics.service'; -import { UsersComponent } from './users/users.component'; -import { UserManagementService } from './users/users.service'; - -@NgModule({ - declarations: [ - UsersComponent, - SettingsComponent, - ExamStatisticsComponent, - ReservationStatisticsComponent, - ResponseStatisticsComponent, - RoomStatisticsComponent, - StatisticsComponent, - ], - imports: [CommonModule, NgbModule, TranslateModule, SessionModule, SharedModule, FormsModule, ReportsModule], - providers: [UserManagementService, SettingsService, StatisticsService], -}) -export class AdministrativeModule {} diff --git a/ui/src/app/administrative/reports/categories/answers-report.component.ts b/ui/src/app/administrative/reports/categories/answers-report.component.ts index d8b18a3e7b..3a8fbd1777 100644 --- a/ui/src/app/administrative/reports/categories/answers-report.component.ts +++ b/ui/src/app/administrative/reports/categories/answers-report.component.ts @@ -12,59 +12,54 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ -import { DatePipe } from '@angular/common'; import { Component } from '@angular/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { format } from 'date-fns'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; import { FileService } from 'src/app/shared/file/file.service'; @Component({ template: ` -
-

- {{ 'sitnet_get_all_exam_answers' | translate }} -

+
+ + {{ 'i18n_get_all_exam_answers' | translate }} +
-
+
-
- +
+
-
- +
+
-
- - +
+
`, selector: 'xm-answers-report', + standalone: true, + imports: [DatePickerComponent, NgbPopover, TranslateModule], }) export class AnswersReportComponent { startDate: Date | null = null; endDate: Date | null = null; - constructor(private datePipe: DatePipe, private files: FileService) {} + constructor(private files: FileService) {} getExamAnswerReport = () => { - const f = this.datePipe.transform(this.startDate || new Date(), 'dd.MM.yyyy'); - const t = this.datePipe.transform(this.endDate || new Date(), 'dd.MM.yyyy'); + const f = format(this.startDate || new Date(), 'dd.MM.yyyy'); + const t = format(this.endDate || new Date(), 'dd.MM.yyyy'); this.files.download(`/app/statistics/allexams/${f}/${t}`, `exam_answers_${f}_${t}.xlsx`); }; diff --git a/ui/src/app/administrative/reports/categories/enrolments-report.component.ts b/ui/src/app/administrative/reports/categories/enrolments-report.component.ts index 3205430097..d0a9831612 100644 --- a/ui/src/app/administrative/reports/categories/enrolments-report.component.ts +++ b/ui/src/app/administrative/reports/categories/enrolments-report.component.ts @@ -12,60 +12,57 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ + import { Component, Input } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { ToastrService } from 'ngx-toastr'; -import { FileService } from '../../../shared/file/file.service'; -import { Option } from '../../../shared/select/dropdown-select.component'; +import { FileService } from 'src/app/shared/file/file.service'; +import { DropdownSelectComponent, Option } from 'src/app/shared/select/dropdown-select.component'; @Component({ template: ` -
-

- {{ 'sitnet_get_all_enrolments_reservations_and_cancelations' | translate }} -

+
+ + {{ 'i18n_get_all_enrolments_reservations_and_cancelations' | translate }} +
-
-
- +
+
+
-
- - +
+
`, selector: 'xm-enrolments-report', + standalone: true, + imports: [DropdownSelectComponent, NgbPopover, TranslateModule], }) export class EnrolmentsReportComponent { @Input() examNames: Option[] = []; enrolment?: number; - constructor(private translate: TranslateService, private toast: ToastrService, private files: FileService) {} + constructor( + private translate: TranslateService, + private toast: ToastrService, + private files: FileService, + ) {} getExamEnrolments = () => { if (this.enrolment) { this.files.download(`/app/statistics/examenrollments/${this.enrolment}`, 'exam_enrolments.xlsx'); } else { - this.toast.error(this.translate.instant('sitnet_choose_exam')); + this.toast.error(this.translate.instant('i18n_choose_exam')); } }; diff --git a/ui/src/app/administrative/reports/categories/exams-report.component.ts b/ui/src/app/administrative/reports/categories/exams-report.component.ts index 5e9efc4523..9f2a737adb 100644 --- a/ui/src/app/administrative/reports/categories/exams-report.component.ts +++ b/ui/src/app/administrative/reports/categories/exams-report.component.ts @@ -12,69 +12,65 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ + import { Component, Input } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { ToastrService } from 'ngx-toastr'; -import { FileService } from '../../../shared/file/file.service'; -import { Option } from '../../../shared/select/dropdown-select.component'; +import { FileService } from 'src/app/shared/file/file.service'; +import { DropdownSelectComponent, Option } from 'src/app/shared/select/dropdown-select.component'; @Component({ template: ` -
-

- {{ 'sitnet_get_all_info_from_exam' | translate }} - {{ 'sitnet_excel_file' | translate }} - {{ 'sitnet_json_file' | translate }} -

+
+ + {{ 'i18n_get_all_info_from_exam' | translate }} + {{ 'i18n_excel_file' | translate }} +
-
-
- - +
+
+ + @if (examNames) { + + }
-
- - +
+
`, selector: 'xm-exams-report', + standalone: true, + imports: [DropdownSelectComponent, NgbPopover, TranslateModule], }) export class ExamsReportComponent { @Input() examNames: Option[] = []; - @Input() fileType = ''; exam?: number; - constructor(private translate: TranslateService, private toast: ToastrService, private files: FileService) {} + constructor( + private translate: TranslateService, + private toast: ToastrService, + private files: FileService, + ) {} examSelected = (event?: Option) => (this.exam = event?.id); getExams = () => { if (this.exam) { - const url = `/app/statistics/examnames/${this.exam}/${this.fileType}`; - const fileName = `exams.${this.fileType}`; + const url = `/app/statistics/examnames/${this.exam}/xlsx`; + const fileName = 'exams.xlsx'; this.files.download(url, fileName); } else { - this.toast.error(this.translate.instant('sitnet_choose_exam')); + this.toast.error(this.translate.instant('i18n_choose_exam')); } }; } diff --git a/ui/src/app/administrative/reports/categories/records-report.component.ts b/ui/src/app/administrative/reports/categories/records-report.component.ts index 9fc8f675b9..f028126a49 100644 --- a/ui/src/app/administrative/reports/categories/records-report.component.ts +++ b/ui/src/app/administrative/reports/categories/records-report.component.ts @@ -1,4 +1,4 @@ -/* +4; /* * Copyright (c) 2018 The members of the EXAM Consortium (https://confluence.csc.fi/display/EXAM/Konsortio-organisaatio) * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent @@ -13,47 +13,42 @@ * See the Licence for the specific language governing permissions and limitations under the Licence. */ import { Component } from '@angular/core'; -import { FileService } from '../../../shared/file/file.service'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; +import { FileService } from 'src/app/shared/file/file.service'; @Component({ template: ` -
-

- {{ 'sitnet_get_graded_logged_csv' | translate }} -

+
+ + {{ 'i18n_get_graded_logged_csv' | translate }} +
-
+
-
- +
+
-
- +
+
-
- - +
+
`, selector: 'xm-records-report', + standalone: true, + imports: [DatePickerComponent, NgbPopover, TranslateModule], }) export class RecordsReportComponent { startDate: Date | null = null; diff --git a/ui/src/app/administrative/reports/categories/reviews-report.component.ts b/ui/src/app/administrative/reports/categories/reviews-report.component.ts index ab03598d4b..707e9273b5 100644 --- a/ui/src/app/administrative/reports/categories/reviews-report.component.ts +++ b/ui/src/app/administrative/reports/categories/reviews-report.component.ts @@ -12,58 +12,53 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ -import { DatePipe } from '@angular/common'; import { Component } from '@angular/core'; -import { FileService } from '../../../shared/file/file.service'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { format } from 'date-fns'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; +import { FileService } from 'src/app/shared/file/file.service'; @Component({ template: ` -
-

- {{ 'sitnet_get_graded_exams' | translate }} -

+
+ + {{ 'i18n_get_graded_exams' | translate }} +
-
-
- +
+
+
-
- +
+
-
- - +
+
`, selector: 'xm-reviews-report', + standalone: true, + imports: [DatePickerComponent, NgbPopover, TranslateModule], }) export class ReviewsReportComponent { startDate: Date | null = null; endDate: Date | null = null; - constructor(private datePipe: DatePipe, private files: FileService) {} + constructor(private files: FileService) {} getReviewsByDate = () => { - const f = this.datePipe.transform(this.startDate || new Date(), 'dd.MM.yyyy'); - const t = this.datePipe.transform(this.endDate || new Date(), 'dd.MM.yyyy'); + const f = format(this.startDate || new Date(), 'dd.MM.yyyy'); + const t = format(this.endDate || new Date(), 'dd.MM.yyyy'); this.files.download(`/app/statistics/reviewsbydate/${f}/${t}`, `reviews_${f}_${t}.xlsx`); }; diff --git a/ui/src/app/administrative/reports/categories/rooms-report.component.ts b/ui/src/app/administrative/reports/categories/rooms-report.component.ts index da073d05ac..f68d8a8ea2 100644 --- a/ui/src/app/administrative/reports/categories/rooms-report.component.ts +++ b/ui/src/app/administrative/reports/categories/rooms-report.component.ts @@ -12,62 +12,58 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ -import { DatePipe } from '@angular/common'; + import { Component, Input } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { format } from 'date-fns'; import { ToastrService } from 'ngx-toastr'; -import type { ExamRoom } from '../../../reservation/reservation.model'; -import { FileService } from '../../../shared/file/file.service'; -import { Option } from '../../../shared/select/dropdown-select.component'; +import type { ExamRoom } from 'src/app/reservation/reservation.model'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; +import { FileService } from 'src/app/shared/file/file.service'; +import { DropdownSelectComponent, Option } from 'src/app/shared/select/dropdown-select.component'; @Component({ template: ` -
-

- {{ 'sitnet_get_all_reservations_from_room' | translate }} -

+
+ + {{ 'i18n_get_all_reservations_from_room' | translate }} +
-
-
- - +
+
+ + @if (rooms) { + + }
-
- +
+
-
- +
+
-
- - +
+
`, selector: 'xm-rooms-report', + standalone: true, + imports: [DropdownSelectComponent, DatePickerComponent, NgbPopover, TranslateModule], }) export class RoomsReportComponent { @Input() rooms: Option[] = []; @@ -79,7 +75,6 @@ export class RoomsReportComponent { constructor( private translate: TranslateService, private toast: ToastrService, - private datePipe: DatePipe, private files: FileService, ) {} @@ -88,12 +83,12 @@ export class RoomsReportComponent { }; getRoomReservationsByDate = () => { - const f = this.datePipe.transform(this.startDate || new Date(), 'dd.MM.yyyy'); - const t = this.datePipe.transform(this.endDate || new Date(), 'dd.MM.yyyy'); + const f = format(this.startDate || new Date(), 'dd.MM.yyyy'); + const t = format(this.endDate || new Date(), 'dd.MM.yyyy'); if (this.room) { this.files.download(`/app/statistics/resbydate/${this.room}/${f}/${t}`, `reservations_${f}_${t}.xlsx`); } else { - this.toast.error(this.translate.instant('sitnet_choose_room')); + this.toast.error(this.translate.instant('i18n_choose_room')); } }; diff --git a/ui/src/app/administrative/reports/categories/students-report.component.ts b/ui/src/app/administrative/reports/categories/students-report.component.ts index e921da85ea..cafc00ef2d 100644 --- a/ui/src/app/administrative/reports/categories/students-report.component.ts +++ b/ui/src/app/administrative/reports/categories/students-report.component.ts @@ -12,62 +12,55 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ -import { DatePipe } from '@angular/common'; import { Component, Input } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { format } from 'date-fns'; import { ToastrService } from 'ngx-toastr'; -import type { User } from '../../../session/session.service'; -import { FileService } from '../../../shared/file/file.service'; -import { Option } from '../../../shared/select/dropdown-select.component'; +import type { User } from 'src/app/session/session.service'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; +import { FileService } from 'src/app/shared/file/file.service'; +import { DropdownSelectComponent, Option } from 'src/app/shared/select/dropdown-select.component'; @Component({ template: ` -
-

- {{ 'sitnet_get_all_student_activities' | translate }} -

+
+ + {{ 'i18n_get_all_student_activities' | translate }} +
-
-
- +
+
+
-
- +
+
-
- +
+
-
- - +
+
`, selector: 'xm-students-report', + standalone: true, + imports: [DropdownSelectComponent, DatePickerComponent, NgbPopover, TranslateModule], }) export class StudentsReportComponent { @Input() students: Option[] = []; @@ -76,7 +69,6 @@ export class StudentsReportComponent { endDate: Date | null = null; constructor( - private datePipe: DatePipe, private translate: TranslateService, private toast: ToastrService, private files: FileService, @@ -84,11 +76,11 @@ export class StudentsReportComponent { getStudentReport = () => { if (this.student) { - const f = this.datePipe.transform(this.startDate || new Date(), 'dd.MM.yyyy'); - const t = this.datePipe.transform(this.endDate || new Date(), 'dd.MM.yyyy'); + const f = format(this.startDate || new Date(), 'dd.MM.yyyy'); + const t = format(this.endDate || new Date(), 'dd.MM.yyyy'); this.files.download(`/app/statistics/student/${this.student}/${f}/${t}`, 'student_activity.xlsx'); } else { - this.toast.error(this.translate.instant('sitnet_choose_student')); + this.toast.error(this.translate.instant('i18n_choose_student')); } }; diff --git a/ui/src/app/administrative/reports/categories/teachers-report.component.ts b/ui/src/app/administrative/reports/categories/teachers-report.component.ts index 55e87f69f0..f6e7a92e36 100644 --- a/ui/src/app/administrative/reports/categories/teachers-report.component.ts +++ b/ui/src/app/administrative/reports/categories/teachers-report.component.ts @@ -12,62 +12,56 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ -import { DatePipe } from '@angular/common'; + import { Component, Input } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { format } from 'date-fns'; import { ToastrService } from 'ngx-toastr'; -import type { User } from '../../../session/session.service'; -import { FileService } from '../../../shared/file/file.service'; -import { Option } from '../../../shared/select/dropdown-select.component'; +import type { User } from 'src/app/session/session.service'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; +import { FileService } from 'src/app/shared/file/file.service'; +import { DropdownSelectComponent, Option } from 'src/app/shared/select/dropdown-select.component'; @Component({ template: ` -
-

- {{ 'sitnet_get_all_teacher_exams' | translate }} -

+
+ + {{ 'i18n_get_all_teacher_exams' | translate }} +
-
-
- +
+
+
-
- +
+
-
- +
+
-
- - +
+
`, selector: 'xm-teachers-report', + standalone: true, + imports: [DropdownSelectComponent, DatePickerComponent, NgbPopover, TranslateModule], }) export class TeachersReportComponent { @Input() teachers: Option[] = []; @@ -76,22 +70,21 @@ export class TeachersReportComponent { answerEndDate: Date | null = null; constructor( - private datePipe: DatePipe, private translate: TranslateService, private toast: ToastrService, private files: FileService, ) {} getTeacherExamsByDate = () => { - const f = this.datePipe.transform(this.answerStartDate || new Date(), 'dd.MM.yyyy'); - const t = this.datePipe.transform(this.answerEndDate || new Date(), 'dd.MM.yyyy'); + const f = format(this.answerStartDate || new Date(), 'dd.MM.yyyy'); + const t = format(this.answerEndDate || new Date(), 'dd.MM.yyyy'); if (this.teacher) { this.files.download( `/app/statistics/teacherexamsbydate/${this.teacher}/${f}/${t}`, `teacherexams_${f}_${t}.xlsx`, ); } else { - this.toast.error(this.translate.instant('sitnet_choose_teacher')); + this.toast.error(this.translate.instant('i18n_choose_teacher')); } }; diff --git a/ui/src/app/administrative/reports/reports.component.scss b/ui/src/app/administrative/reports/reports.component.scss new file mode 100644 index 0000000000..86507cbfb1 --- /dev/null +++ b/ui/src/app/administrative/reports/reports.component.scss @@ -0,0 +1,25 @@ +.report-category { + border: 1px solid lightgrey; + border-radius: 4pt; + padding: 1em; + margin-bottom: 1em; + + .dropdown > button { + width: 100%; + display: inline-flex; + justify-content: space-between; + align-items: center; + } + + .print-btn { + background-color: #6aa33a; + color: white; + width: 38px; + height: 38px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 2px; + margin-left: auto; + } +} diff --git a/ui/src/app/administrative/reports/reports.component.ts b/ui/src/app/administrative/reports/reports.component.ts index db752e7e43..5bbc59c372 100644 --- a/ui/src/app/administrative/reports/reports.component.ts +++ b/ui/src/app/administrative/reports/reports.component.ts @@ -12,45 +12,58 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ + import type { OnInit } from '@angular/core'; import { Component } from '@angular/core'; -import { RoomService } from '../../facility/rooms/room.service'; -import { ExamRoom } from '../../reservation/reservation.model'; -import { User } from '../../session/session.service'; -import { Option } from '../../shared/select/dropdown-select.component'; -import { UserService } from '../../shared/user/user.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { RoomService } from 'src/app/facility/rooms/room.service'; +import { ExamRoom } from 'src/app/reservation/reservation.model'; +import { User } from 'src/app/session/session.service'; +import { PageContentComponent } from 'src/app/shared/components/page-content.component'; +import { PageHeaderComponent } from 'src/app/shared/components/page-header.component'; +import { Option } from 'src/app/shared/select/dropdown-select.component'; +import { UserService } from 'src/app/shared/user/user.service'; +import { AnswersReportComponent } from './categories/answers-report.component'; +import { EnrolmentsReportComponent } from './categories/enrolments-report.component'; +import { ExamsReportComponent } from './categories/exams-report.component'; +import { RecordsReportComponent } from './categories/records-report.component'; +import { ReviewsReportComponent } from './categories/reviews-report.component'; +import { RoomsReportComponent } from './categories/rooms-report.component'; +import { StudentsReportComponent } from './categories/students-report.component'; +import { TeachersReportComponent } from './categories/teachers-report.component'; import { ReportsService, UserRole } from './reports.service'; @Component({ selector: 'xm-reports', template: ` -
-
-
- {{ 'sitnet_reports' | translate }} -
-
- -
-
-
- -
-
- -
-
- -
-
-
-
-
- -
-
-
+ + + +
+
+
+
+
+
+
+
+
`, + standalone: true, + imports: [ + RoomsReportComponent, + ExamsReportComponent, + StudentsReportComponent, + EnrolmentsReportComponent, + AnswersReportComponent, + ReviewsReportComponent, + RecordsReportComponent, + TeachersReportComponent, + TranslateModule, + PageHeaderComponent, + PageContentComponent, + ], + styleUrl: './reports.component.scss', }) export class ReportsComponent implements OnInit { rooms: Option[] = []; @@ -58,7 +71,11 @@ export class ReportsComponent implements OnInit { teachers: Option[] = []; students: Option[] = []; - constructor(private Users: UserService, private Reports: ReportsService, private Room: RoomService) {} + constructor( + private Users: UserService, + private Reports: ReportsService, + private Room: RoomService, + ) {} ngOnInit() { this.Room.getRooms$().subscribe((resp) => { @@ -80,7 +97,7 @@ export class ReportsComponent implements OnInit { this.Users.listUsersByRole$(UserRole.TEACHER).subscribe((resp) => { this.teachers = resp.map((t) => ({ id: t.id, - label: t.name as string, + label: t.firstName + ' ' + t.lastName, value: t, })); }); @@ -88,7 +105,7 @@ export class ReportsComponent implements OnInit { this.Users.listUsersByRole$(UserRole.STUDENT).subscribe((resp) => { this.students = resp.map((t) => ({ id: t.id, - label: t.name as string, + label: t.firstName + ' ' + t.lastName, value: t, })); }); diff --git a/ui/src/app/administrative/reports/reports.module.ts b/ui/src/app/administrative/reports/reports.module.ts deleted file mode 100644 index 663b8d65fe..0000000000 --- a/ui/src/app/administrative/reports/reports.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { CommonModule, DatePipe } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateModule } from '@ngx-translate/core'; -import { FacilityModule } from '../../facility/facility.module'; -import { SharedModule } from '../../shared/shared.module'; -import { AnswersReportComponent } from './categories/answers-report.component'; -import { EnrolmentsReportComponent } from './categories/enrolments-report.component'; -import { ExamsReportComponent } from './categories/exams-report.component'; -import { RecordsReportComponent } from './categories/records-report.component'; -import { ReviewsReportComponent } from './categories/reviews-report.component'; -import { RoomsReportComponent } from './categories/rooms-report.component'; -import { StudentsReportComponent } from './categories/students-report.component'; -import { TeachersReportComponent } from './categories/teachers-report.component'; -import { ReportsComponent } from './reports.component'; -import { ReportsService } from './reports.service'; - -@NgModule({ - imports: [SharedModule, CommonModule, TranslateModule, FacilityModule, NgbModule], - declarations: [ - AnswersReportComponent, - EnrolmentsReportComponent, - ExamsReportComponent, - RecordsReportComponent, - ReviewsReportComponent, - RoomsReportComponent, - StudentsReportComponent, - TeachersReportComponent, - ReportsComponent, - ], - providers: [ReportsService, DatePipe], -}) -export class ReportsModule {} diff --git a/ui/src/app/administrative/settings/settings.component.html b/ui/src/app/administrative/settings/settings.component.html index 8292470e95..bba3f1c16e 100644 --- a/ui/src/app/administrative/settings/settings.component.html +++ b/ui/src/app/administrative/settings/settings.component.html @@ -1,13 +1,11 @@ -
-
- {{ 'sitnet_settings' | translate }} -
-
- -
-
-
- + +@if (config) { + +} + +
+
+
-
-
+
+
-
-
- +
+
+
-
-
-
+
-
-
+
+
{{ 'i18n_reservation_window' | translate }} ({{ 'i18n_days' | translate }})
-
-
-
+
-
- {{ 'sitnet_exam_instance_settings' | translate }} -
    -
  • - {{ 'sitnet_interoperable' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_exam_collaboration_supported' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_anonymous_review' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_course_integration_support' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
      -
    • - {{ item.key }}: {{ item.value }} -
    • -
    -
  • - {{ 'sitnet_enrolment_check_integration_support' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_supports_maturity' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_supports_printouts' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_role_mapping' | translate }} -
  • +
    + {{ 'i18n_exam_instance_settings' | translate }} + @if (config) {
    • - {{ 'sitnet_student' | translate }}:  - {{ - config.roles.STUDENT.join( - ', - ' - ) + {{ 'i18n_interoperable' | translate }}:  + @if (config.isExamVisitSupported) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.isExamVisitSupported) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_exam_collaboration_supported' | translate }}:  + @if (config.isExamCollaborationSupported) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.isExamCollaborationSupported) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_anonymous_review' | translate }}:  + @if (config.anonymousReviewEnabled) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.anonymousReviewEnabled) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_course_integration_support' | translate }}:  + @if (config.hasCourseSearchIntegration) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.hasCourseSearchIntegration) { + {{ 'DIALOGS_NO' | translate }} + } +
    • + @if (config.hasCourseSearchIntegration) { +
        + @for (item of config.courseSearchIntegrationUrls | keyvalue; track item) { +
      • + {{ item.key }}: {{ item.value }} +
      • + } +
      + } +
    • + {{ 'i18n_enrolment_check_integration_support' | translate }}:  + @if (config.hasEnrolmentCheckIntegration) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.hasEnrolmentCheckIntegration) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_supports_maturity' | translate }}:  + @if (config.supportsMaturity) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.supportsMaturity) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_supports_printouts' | translate }}:  + @if (config.supportsPrintouts) { + {{ 'DIALOGS_YES' | translate }} + } + @if (!config.supportsPrintouts) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_role_mapping' | translate }} +
    • +
        +
      • + {{ 'i18n_student' | translate }}:  + {{ config.roles.STUDENT.join(', ') }} +
      • +
      • + {{ 'i18n_teacher' | translate }}:  + {{ config.roles.TEACHER.join(', ') }} +
      • +
      • + {{ 'i18n_admin' | translate }}:  {{ config.roles.ADMIN.join(', ') }} +
      • +
      +
    • + {{ 'i18n_exam_durations' | translate }}:  + {{ config.examDurations.join(', ') }} +
    • +
    • + {{ 'i18n_grade_scale_overridable' | translate }}:  + @if (!config.isGradeScaleOverridable) { + {{ 'DIALOGS_YES' | translate }} + } + @if (config.isGradeScaleOverridable) { + {{ 'DIALOGS_NO' | translate }} + } +
    • +
    • + {{ 'i18n_attachment_max_size' | translate }}: {{ + config.maxFileSize / 1000000 }} + MB
    • - {{ 'sitnet_teacher' | translate }}:  - {{ - config.roles.TEACHER.join( - ', - ' - ) + {{ 'i18n_exam_expiration_period' | translate }}: {{ + config.expirationPeriod }}
    • - {{ 'sitnet_admin' | translate }}:  {{ config.roles.ADMIN.join(', ') }} + {{ 'i18n_default_timezone' | translate }}: {{ config.defaultTimeZone }}
    -
  • - {{ 'sitnet_exam_durations' | translate }}: {{ - config.examDurations.join( - ', - ' - ) - }} -
  • -
  • - {{ 'sitnet_grade_scale_overridable' | translate }}:  - {{ 'DIALOGS_YES' | translate }} - {{ 'DIALOGS_NO' | translate }} -
  • -
  • - {{ 'sitnet_attachment_max_size' | translate }}: {{ - config.maxFileSize / 1000000 - }} - MB -
  • -
  • - {{ 'sitnet_exam_expiration_period' | translate }}: {{ - config.expirationPeriod - }} -
  • - -
  • - {{ 'sitnet_default_timezone' | translate }}: {{ config.defaultTimeZone }} -
  • -
+ }
-
- {{ 'sitnet_show_http_headers' | translate }} +
+ {{ 'i18n_show_http_headers' | translate }}
    -
  • - {{ item.key }}: {{ item.value }} -
  • + @for (item of attributes | keyvalue; track item) { +
  • + {{ item.key }}: {{ item.value }} +
  • + }
-
+ diff --git a/ui/src/app/administrative/settings/settings.component.ts b/ui/src/app/administrative/settings/settings.component.ts index c716abbd66..7be0e25133 100644 --- a/ui/src/app/administrative/settings/settings.component.ts +++ b/ui/src/app/administrative/settings/settings.component.ts @@ -1,18 +1,38 @@ +import { KeyValuePipe } from '@angular/common'; import type { OnInit } from '@angular/core'; import { Component } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { FormsModule } from '@angular/forms'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { ToastrService } from 'ngx-toastr'; +import { CKEditorComponent } from 'src/app/shared/ckeditor/ckeditor.component'; +import { PageContentComponent } from 'src/app/shared/components/page-content.component'; +import { PageHeaderComponent } from 'src/app/shared/components/page-header.component'; import { AppConfig, SettingsService } from './settings.service'; @Component({ templateUrl: './settings.component.html', selector: 'xm-settings', + standalone: true, + imports: [ + CKEditorComponent, + FormsModule, + NgbPopover, + KeyValuePipe, + TranslateModule, + PageHeaderComponent, + PageContentComponent, + ], }) export class SettingsComponent implements OnInit { config!: AppConfig; attributes: string[] = []; - constructor(private Settings: SettingsService, private toast: ToastrService, private translate: TranslateService) {} + constructor( + private Settings: SettingsService, + private toast: ToastrService, + private translate: TranslateService, + ) {} ngOnInit() { this.Settings.getConfig$().subscribe((resp) => (this.config = resp)); @@ -29,7 +49,7 @@ export class SettingsComponent implements OnInit { this.Settings.updateReservationWindow$(this.config).subscribe({ next: this.onSuccess, error: this.onError }); private onSuccess = () => - this.toast.info(this.translate.instant('sitnet_settings') + ' ' + this.translate.instant('sitnet_updated')); + this.toast.info(this.translate.instant('i18n_settings') + ' ' + this.translate.instant('i18n_updated')); private onError = (error: string) => this.toast.error(error); } diff --git a/ui/src/app/administrative/statistics/categories/exam-statistics.component.ts b/ui/src/app/administrative/statistics/categories/exam-statistics.component.ts index 01d6be8823..fcfc12a82e 100644 --- a/ui/src/app/administrative/statistics/categories/exam-statistics.component.ts +++ b/ui/src/app/administrative/statistics/categories/exam-statistics.component.ts @@ -1,57 +1,67 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import type { ExamInfo, QueryParams } from '../statistics.service'; -import { StatisticsService } from '../statistics.service'; +import { TranslateModule } from '@ngx-translate/core'; +import type { ExamInfo, QueryParams } from 'src/app/administrative/statistics/statistics.service'; +import { StatisticsService } from 'src/app/administrative/statistics/statistics.service'; @Component({ template: ` -
-
- +
+
+
-
-
-

{{ 'sitnet_most_popular_exams' | translate }}

+
+
+ {{ 'i18n_most_popular_exams' | translate }}
-
-
- - - - - - - - - - - - - - - - - - - - - -
{{ 'sitnet_rank' | translate }}{{ 'sitnet_exam' | translate }}{{ 'sitnet_amount_exams' | translate }}
{{ getRank(i, exams) }}.{{ exam.name }}{{ exam.participations }}
- {{ 'sitnet_total' | translate }} - - {{ totalExams() }} -
-
+
+ @if (exams.length > 0) { +
+ + + + + + + + + + @for (exam of exams; track exam; let i = $index) { + + + + + + } + + + + + + + +
{{ 'i18n_rank' | translate }}{{ 'i18n_exam' | translate }}{{ 'i18n_amount_exams' | translate }}
{{ exam.rank }}.{{ exam.name }}{{ exam.participations }}
+ {{ 'i18n_total' | translate }} + + @if (exams) { + {{ totalExams }} + } +
+
+ }
`, selector: 'xm-exam-statistics', + standalone: true, + imports: [TranslateModule], }) export class ExamStatisticsComponent implements OnInit { @Input() queryParams: QueryParams = {}; exams: ExamInfo[] = []; + totalExams = 0; constructor(private Statistics: StatisticsService) {} @@ -59,28 +69,18 @@ export class ExamStatisticsComponent implements OnInit { this.listExams(); } - totalExams = () => this.exams.reduce((a, b) => a + b.participations, 0); - listExams = () => this.Statistics.listExams$(this.queryParams).subscribe((resp) => { - this.exams = resp.sort((a, b) => { - if (a.participations > b.participations) return -1; - else if (a.participations < b.participations) return 1; - - if (a.name > b.name) return 1; - else if (a.name < b.name) return -1; - - return 0; - }); + this.exams = resp + .map((e) => ({ + ...e, + rank: resp.filter((e2) => e2.participations > e.participations).length + 1, + })) + .sort((a, b) => { + if (a.rank < b.rank) return -1; + else if (a.rank > b.rank) return 1; + else return a.name.localeCompare(b.name); + }); + this.totalExams = this.exams.reduce((a, b) => a + b.participations, 0); }); - - getRank = (index: number, items: ExamInfo[]) => { - const prev = Math.max(0, index - 1); - if (items[prev].participations === items[index].participations) { - items[index].rank = items[prev].rank || 0; - return (items[prev].rank || 0) + 1; - } - items[index].rank = index; - return index + 1; - }; } diff --git a/ui/src/app/administrative/statistics/categories/reservation-statistics.component.ts b/ui/src/app/administrative/statistics/categories/reservation-statistics.component.ts index 536c9455fd..c9d0266640 100644 --- a/ui/src/app/administrative/statistics/categories/reservation-statistics.component.ts +++ b/ui/src/app/administrative/statistics/categories/reservation-statistics.component.ts @@ -14,38 +14,40 @@ */ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import type { QueryParams } from '../statistics.service'; -import { StatisticsService } from '../statistics.service'; +import { TranslateModule } from '@ngx-translate/core'; +import type { QueryParams } from 'src/app/administrative/statistics/statistics.service'; +import { StatisticsService } from 'src/app/administrative/statistics/statistics.service'; @Component({ template: ` -
-
+
+
-
-
- {{ 'sitnet_total_reservations' | translate }}: +
+
+ {{ 'i18n_total_reservations' | translate }}:
-
{{ reservations.length }}
+
{{ data.appearances }}
-
-
- {{ 'sitnet_total_no_shows' | translate }}: +
+
+ {{ 'i18n_total_no_shows' | translate }}:
-
{{ noShows.length }}
+
{{ data.noShows }}
`, selector: 'xm-reservation-statistics', + standalone: true, + imports: [TranslateModule], }) export class ReservationStatisticsComponent implements OnInit { @Input() queryParams: QueryParams = {}; - reservations: { noShow: boolean }[] = []; - noShows: { noShow: boolean }[] = []; + data = { noShows: 0, appearances: 0 }; constructor(private Statistics: StatisticsService) {} @@ -55,7 +57,6 @@ export class ReservationStatisticsComponent implements OnInit { listReservations = () => this.Statistics.listReservations$(this.queryParams).subscribe((resp) => { - this.reservations = resp.filter((r) => !r.noShow); - this.noShows = resp.filter((r) => r.noShow); + this.data = resp; }); } diff --git a/ui/src/app/administrative/statistics/categories/response-statistics.component.ts b/ui/src/app/administrative/statistics/categories/response-statistics.component.ts index 91849f3c69..2b3ece81fa 100644 --- a/ui/src/app/administrative/statistics/categories/response-statistics.component.ts +++ b/ui/src/app/administrative/statistics/categories/response-statistics.component.ts @@ -12,45 +12,47 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ + import type { OnInit } from '@angular/core'; -import { Component, Input } from '@angular/core'; -import type { Exam } from '../../../exam/exam.model'; -import type { QueryParams } from '../statistics.service'; -import { StatisticsService } from '../statistics.service'; +import { Component, Input, signal } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; +import type { QueryParams } from 'src/app/administrative/statistics/statistics.service'; +import { StatisticsService } from 'src/app/administrative/statistics/statistics.service'; @Component({ template: ` -
-
- +
+
+
-
-
- {{ 'sitnet_assessed_exams' | translate }}: +
+
+ {{ 'i18n_assessed_exams' | translate }}:
-
{{ assessedExams.length }}
+
{{ data().assessed }}
-
-
- {{ 'sitnet_unassessed_exams' | translate }}: +
+
+ {{ 'i18n_unassessed_exams' | translate }}:
-
{{ unassessedExams.length }}
+
{{ data().unAssessed }}
-
-
- {{ 'sitnet_aborted_exams' | translate }}: +
+
+ {{ 'i18n_aborted_exams' | translate }}:
-
{{ abortedExams.length }}
+
{{ data().aborted }}
`, selector: 'xm-response-statistics', + standalone: true, + imports: [TranslateModule], }) export class ResponseStatisticsComponent implements OnInit { @Input() queryParams: QueryParams = {}; - assessedExams: Exam[] = []; - unassessedExams: Exam[] = []; - abortedExams: Exam[] = []; + + data = signal({ assessed: 0, unAssessed: 0, aborted: 0 }); constructor(private Statistics: StatisticsService) {} @@ -58,14 +60,5 @@ export class ResponseStatisticsComponent implements OnInit { this.listResponses(); } - listResponses = () => - this.Statistics.listResponses$(this.queryParams).subscribe((resp) => { - this.assessedExams = resp.filter( - (e) => ['GRADED', 'GRADED_LOGGED', 'ARCHIVED', 'REJECTED', 'DELETED'].indexOf(e.state) > -1, - ); - this.unassessedExams = resp.filter( - (e) => ['STUDENT_STARTED', 'REVIEW', 'REVIEW_STARTED'].indexOf(e.state) > -1, - ); - this.abortedExams = resp.filter((e) => e.state === 'ABORTED'); - }); + listResponses = () => this.Statistics.listResponses$(this.queryParams).subscribe((resp) => this.data.set(resp)); } diff --git a/ui/src/app/administrative/statistics/categories/room-statistics.component.ts b/ui/src/app/administrative/statistics/categories/room-statistics.component.ts index 3f9372ec2f..250f74e6f3 100644 --- a/ui/src/app/administrative/statistics/categories/room-statistics.component.ts +++ b/ui/src/app/administrative/statistics/categories/room-statistics.component.ts @@ -12,43 +12,64 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ +import { DatePipe } from '@angular/common'; import { Component, Input } from '@angular/core'; -import type { ExamParticipation } from '../../../exam/exam.model'; -import type { Participations, QueryParams } from '../statistics.service'; -import { StatisticsService } from '../statistics.service'; +import { TranslateModule } from '@ngx-translate/core'; +import type { Participations, QueryParams } from 'src/app/administrative/statistics/statistics.service'; +import { StatisticsService } from 'src/app/administrative/statistics/statistics.service'; @Component({ template: ` -
-
+
+
-
-
+
+
- - - - + + + @for (room of rooms; track room) { + + } + - - - - - - + @for (month of months; track month.toISOString()) { + + + + @for (room of rooms; track room) { + + } + + + } - + - + @for (room of rooms; track room) { + + } @@ -59,6 +80,8 @@ import { StatisticsService } from '../statistics.service'; `, selector: 'xm-room-statistics', + standalone: true, + imports: [DatePipe, TranslateModule], }) export class RoomStatisticsComponent { @Input() queryParams: QueryParams = {}; @@ -82,8 +105,8 @@ export class RoomStatisticsComponent { totalParticipations = (month?: Date, room?: string) => { if (!this.participations) return 0; - const isWithinBounds = (p: ExamParticipation) => { - const date = new Date(p.externalExam ? p.externalExam.started : p.exam.created); + const isWithinBounds = (data: { date: string }) => { + const date = new Date(data.date); const current = month ? new Date(month) : new Date(); const min = new Date(current.getFullYear(), current.getMonth(), 1); const max = new Date(current.getFullYear(), current.getMonth() + 1, 0, 23, 59, 59); @@ -119,12 +142,7 @@ export class RoomStatisticsComponent { private getMinAndMaxDates = (): { min: Date; max: Date } => { const dates: Date[] = Object.values(this.participations) - .flatMap((ps) => - ps - .filter((p) => p.exam || p.externalExam) - .map((p) => (p.externalExam ? p.externalExam.started : p.exam.created)) - .map((d) => new Date(d)), - ) + .flatMap((ps) => ps.map((d) => new Date(d.date))) .sort((a, b) => a.getTime() - b.getTime()); let minDate = dates[0]; // Set min date to which one is earlier: participation or search date diff --git a/ui/src/app/administrative/statistics/statistics.component.html b/ui/src/app/administrative/statistics/statistics.component.html index d5b67a7d9e..88b5e285eb 100644 --- a/ui/src/app/administrative/statistics/statistics.component.html +++ b/ui/src/app/administrative/statistics/statistics.component.html @@ -1,54 +1,50 @@ -
-
- {{ 'sitnet_statistics' | translate }} -
-
- -
+ + + -
-
+ -
+
-
-

{{ 'sitnet_begin' | translate }}

+
+ {{ 'i18n_begin' | translate }}
-
-

{{ 'sitnet_end' | translate }}

+
+ {{ 'i18n_end' | translate }}
-
-

{{ 'sitnet_department' | translate }}

- +
+ {{ 'i18n_department' | translate }} +
{{ 'sitnet_department' | translate }} (change)="handleDepartmentInputChange()" type="text" class="form-control" - placeholder="{{ 'sitnet_search' | translate }}" + placeholder="{{ 'i18n_search' | translate }}" />
@@ -78,41 +74,42 @@

{{ 'sitnet_department' | translate }}

- -
- -
-
-
    -
  • - + @for (department of filteredDepartments; track department) { - -
  • -
+ } +
+
+
+
+ @for (department of departments; track department) { + @if (department.filtered) { + + {{ department.name }} + + } + }
- - - - -
+ @if (view === 'ROOMS') { + + } + @if (view === 'RESERVATIONS') { + + } + @if (view === 'RESPONSES') { + + } + @if (view === 'EXAMS') { + + } + diff --git a/ui/src/app/administrative/statistics/statistics.component.ts b/ui/src/app/administrative/statistics/statistics.component.ts index 0cc658c533..0469b2f374 100644 --- a/ui/src/app/administrative/statistics/statistics.component.ts +++ b/ui/src/app/administrative/statistics/statistics.component.ts @@ -12,8 +12,28 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ +import { NgClass } from '@angular/common'; import type { OnInit } from '@angular/core'; import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { + NgbDropdown, + NgbDropdownItem, + NgbDropdownMenu, + NgbDropdownToggle, + NgbNav, + NgbNavItem, + NgbNavItemRole, + NgbNavLink, +} from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { PageContentComponent } from 'src/app/shared/components/page-content.component'; +import { PageHeaderComponent } from 'src/app/shared/components/page-header.component'; +import { DatePickerComponent } from 'src/app/shared/date/date-picker.component'; +import { ExamStatisticsComponent } from './categories/exam-statistics.component'; +import { ReservationStatisticsComponent } from './categories/reservation-statistics.component'; +import { ResponseStatisticsComponent } from './categories/response-statistics.component'; +import { RoomStatisticsComponent } from './categories/room-statistics.component'; import { QueryParams, StatisticsService } from './statistics.service'; interface Departments { @@ -31,6 +51,27 @@ enum Tab { @Component({ templateUrl: './statistics.component.html', selector: 'xm-statistics', + standalone: true, + imports: [ + NgbNav, + NgbNavItem, + NgbNavItemRole, + NgbNavLink, + DatePickerComponent, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + FormsModule, + NgbDropdownItem, + NgClass, + RoomStatisticsComponent, + ReservationStatisticsComponent, + ResponseStatisticsComponent, + ExamStatisticsComponent, + TranslateModule, + PageHeaderComponent, + PageContentComponent, + ], }) export class StatisticsComponent implements OnInit { view: Tab = Tab.RESPONSES; diff --git a/ui/src/app/administrative/statistics/statistics.service.ts b/ui/src/app/administrative/statistics/statistics.service.ts index 14c27134b4..c777bae499 100644 --- a/ui/src/app/administrative/statistics/statistics.service.ts +++ b/ui/src/app/administrative/statistics/statistics.service.ts @@ -1,6 +1,5 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Exam, ExamParticipation } from 'src/app/exam/exam.model'; export type QueryParams = { start?: string; end?: string; dept?: string }; export type ExamInfo = { @@ -10,7 +9,7 @@ export type ExamInfo = { rank: number; }; export type Participations = { - [room: string]: ExamParticipation[]; + [room: string]: { date: string }[]; }; @Injectable({ providedIn: 'root' }) @@ -20,8 +19,11 @@ export class StatisticsService { listDepartments$ = () => this.http.get<{ departments: string[] }>('/app/reports/departments'); listExams$ = (params: QueryParams) => this.http.get('/app/reports/exams', { params: params }); listReservations$ = (params: QueryParams) => - this.http.get<{ noShow: boolean }[]>('/app/reports/reservations', { params: params }); - listResponses$ = (params: QueryParams) => this.http.get('/app/reports/responses', { params: params }); + this.http.get<{ noShows: number; appearances: number }>('/app/reports/reservations', { params: params }); + listResponses$ = (params: QueryParams) => + this.http.get<{ assessed: number; unAssessed: number; aborted: number }>('/app/reports/responses', { + params: params, + }); listParticipations$ = (params: QueryParams) => this.http.get('/app/reports/participations', { params: params }); } diff --git a/ui/src/app/administrative/users/users.component.html b/ui/src/app/administrative/users/users.component.html index feed9df35e..eb5258fe0a 100644 --- a/ui/src/app/administrative/users/users.component.html +++ b/ui/src/app/administrative/users/users.component.html @@ -1,25 +1,22 @@ -
-
- {{ 'sitnet_user_administration' | translate }} -
-
-
-
- -
-
-
+ + + +
+
+ +
+
@@ -29,7 +26,9 @@
- +
+
+
- + @for (role of roles; track role) { + + }
- - - +
+
+
+
- + @for (permission of permissions; track permission) { + + }
- +
-
+
-
+
{{ 'sitnet_year' | translate }}{{ 'sitnet_month' | translate }}{{ room.split('___')[1] }}{{ 'sitnet_total' | translate }} + {{ 'i18n_year' | translate }} + + {{ 'i18n_month' | translate }} + {{ room.split('___')[1] }} + {{ 'i18n_total' | translate }} +
{{ month | date : 'yyyy' }}{{ month | date : 'M' }}{{ totalParticipations(month, room) }}{{ totalParticipations(month) }}
+ {{ month | date: 'yyyy' }} + + {{ month | date: 'M' }} + {{ totalParticipations(month, room) }} + {{ totalParticipations(month) }} +
- {{ 'sitnet_total' | translate }} + {{ 'i18n_total' | translate }} {{ totalParticipations(undefined, room) }}{{ totalParticipations(undefined, room) }} {{ totalParticipations() }}
- - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + - + - + @if (user.removablePermissions.length > 0) { + + } + + + + + }
{{ 'sitnet_lastname' | translate }}{{ 'sitnet_firstname' | translate }}{{ 'sitnet_email' | translate }}{{ 'sitnet_userid' | translate }}{{ 'sitnet_employeeno' | translate }}{{ 'sitnet_last_login' | translate }}{{ 'sitnet_user_roles' | translate }}{{ 'sitnet_user_permissions' | translate }}{{ 'i18n_lastname' | translate }}{{ 'i18n_firstname' | translate }}{{ 'i18n_email' | translate }}{{ 'i18n_userid' | translate }}{{ 'i18n_employeeno' | translate }}{{ 'i18n_last_login' | translate }}{{ 'i18n_user_roles' | translate }}{{ 'i18n_user_permissions' | translate }}
{{ user.lastName }}{{ user.firstName }} - {{ user.email }} - {{ user.userIdentifier }}{{ user.employeeNumber }}{{ user.lastLogin | date : 'dd.MM.yyyy HH:mm:ss' }} - - - - -
- - -
- + @for ( + user of filteredUsers | slice: currentPage * pageSize : currentPage * pageSize + pageSize; + track user + ) { +
{{ user.lastName }}{{ user.firstName }} + {{ user.email }} + {{ user.userIdentifier }}{{ user.employeeNumber }}{{ user.lastLogin | date: 'dd.MM.yyyy HH:mm:ss' }} + @if (hasRole(user, 'ADMIN')) { + + } + @if (hasRole(user, 'TEACHER')) { + + } + @if (hasRole(user, 'STUDENT')) { + + } +
+ -
- - - - - - -
- - -
- - - +
+ @if (hasPermission(user, 'CAN_INSPECT_LANGUAGE')) { + + } + @if (hasPermission(user, 'CAN_CREATE_BYOD_EXAM')) { + + } +
+ -
- - - - - - -
-
- -
+ @if (filteredUsers.length > pageSize) { +
+ +
+ }
-
+ diff --git a/ui/src/app/administrative/users/users.component.ts b/ui/src/app/administrative/users/users.component.ts index fc3c5dd6ca..51d1793568 100644 --- a/ui/src/app/administrative/users/users.component.ts +++ b/ui/src/app/administrative/users/users.component.ts @@ -1,11 +1,23 @@ +import { DatePipe, NgClass, SlicePipe } from '@angular/common'; import type { OnInit } from '@angular/core'; import { Component, OnDestroy } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { FormsModule } from '@angular/forms'; +import { + NgbDropdown, + NgbDropdownItem, + NgbDropdownMenu, + NgbDropdownToggle, + NgbPopover, +} from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { ToastrService } from 'ngx-toastr'; import { Subject } from 'rxjs'; import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; -import type { User } from '../../session/session.service'; -import { SessionService } from '../../session/session.service'; +import type { User } from 'src/app/session/session.service'; +import { SessionService } from 'src/app/session/session.service'; +import { PageContentComponent } from 'src/app/shared/components/page-content.component'; +import { PageHeaderComponent } from 'src/app/shared/components/page-header.component'; +import { PaginatorComponent } from 'src/app/shared/paginator/paginator.component'; import type { Permission } from './users.service'; import { PermissionType, UserManagementService } from './users.service'; @@ -32,6 +44,31 @@ interface UserWithOptions extends User { @Component({ templateUrl: './users.component.html', selector: 'xm-users', + standalone: true, + imports: [ + FormsModule, + NgbPopover, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownItem, + NgClass, + PaginatorComponent, + SlicePipe, + DatePipe, + TranslateModule, + PageHeaderComponent, + PageContentComponent, + ], + styles: [ + ` + .flex-wrap-gap { + display: flex; + gap: 10px; + flex-wrap: wrap; + } + `, + ], }) export class UsersComponent implements OnInit, OnDestroy { users: UserWithOptions[] = []; @@ -42,9 +79,9 @@ export class UsersComponent implements OnInit, OnDestroy { textChanged = new Subject(); ngUnsubscribe = new Subject(); roles: RoleOption[] = [ - { type: 'ADMIN', name: 'sitnet_admin', icon: 'bi-gear' }, - { type: 'TEACHER', name: 'sitnet_teacher', icon: 'bi-person-fill' }, - { type: 'STUDENT', name: 'sitnet_student', icon: 'bi-person' }, + { type: 'ADMIN', name: 'i18n_admin', icon: 'bi-gear' }, + { type: 'TEACHER', name: 'i18n_teacher', icon: 'bi-person' }, + { type: 'STUDENT', name: 'i18n_student', icon: 'bi-mortarboard' }, ]; permissions: PermissionOption[] = []; loader = { loading: false }; @@ -74,8 +111,15 @@ export class UsersComponent implements OnInit, OnDestroy { if (p.type === PermissionType.CAN_INSPECT_LANGUAGE) { return { ...p, - name: 'sitnet_can_inspect_language', - icon: 'bi-pencil', + name: 'i18n_can_inspect_language', + icon: 'bi-alphabet', + }; + } + if (p.type === PermissionType.CAN_CREATE_BYOD_EXAM) { + return { + ...p, + name: 'i18n_can_create_byod_exam', + icon: 'bi-house-gear', }; } diff --git a/ui/src/app/administrative/users/users.service.ts b/ui/src/app/administrative/users/users.service.ts index aa31e2a9bc..93d97b20ba 100644 --- a/ui/src/app/administrative/users/users.service.ts +++ b/ui/src/app/administrative/users/users.service.ts @@ -1,9 +1,10 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import type { Role, User } from '../../session/session.service'; +import type { Role, User } from 'src/app/session/session.service'; export enum PermissionType { CAN_INSPECT_LANGUAGE = 'CAN_INSPECT_LANGUAGE', + CAN_CREATE_BYOD_EXAM = 'CAN_CREATE_BYOD_EXAM', } export interface Permission { diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts deleted file mode 100644 index d13a97cfd5..0000000000 --- a/ui/src/app/app-routing.module.ts +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2017 Exam Consortium - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ -import { NgModule } from '@angular/core'; -import { Route, RouterModule } from '@angular/router'; -import { AppComponent } from './app.component'; -import { CalendarTitleResolverService } from './calendar/calendar-title-resolver.service'; -import { CalendarComponent } from './calendar/calendar.component'; -import { StudentDashboardComponent } from './dashboard/student/student-dashboard.component'; -import { ExamEnrolmentTitleResolverService } from './enrolment/exams/exam-enrolment-title-resolver.service'; -import { ExamEnrolmentsComponent } from './enrolment/exams/exam-enrolments.component'; -import { CollaborativeParticipationsComponent } from './enrolment/finished/collaborative-exam-participations.component'; -import { ExamParticipationsComponent } from './enrolment/finished/exam-participations.component'; -import { CollaborativeExamSearchComponent } from './enrolment/search/collaborative-exam-search.component'; -import { ExamSearchComponent } from './enrolment/search/exam-search.component'; -import { WaitingRoomComponent } from './enrolment/waiting-room/waiting-room.component'; -import { WrongLocationComponent } from './enrolment/wrong-location/wrong-location.component'; -import { ExaminationComponent } from './examination/examination.component'; -import { ExaminationLogoutComponent } from './examination/logout/examination-logout.component'; -import { LogoutComponent } from './session/logout/logout.component'; - -const routes: Route[] = [ - { - path: '', - component: AppComponent, - pathMatch: 'full', - title: 'EXAM', - }, - { - path: 'dashboard', - component: StudentDashboardComponent, - title: 'EXAM', - }, - { - path: 'logout', - component: LogoutComponent, - }, - { - path: 'exam/:hash', - component: ExaminationComponent, - data: { - isPreview: false, - }, - title: 'EXAM - examination', - }, - { - path: 'waitingroom/:id/:hash', - component: WaitingRoomComponent, - title: 'EXAM - waiting room', - }, - { - path: 'waitingroom', - component: WaitingRoomComponent, - title: 'EXAM - waiting room', - }, - { - path: 'wrongroom/:eid/:mid', - component: WrongLocationComponent, - data: { - cause: 'room', - }, - title: 'EXAM - wrong location', - }, - { - path: 'wrongmachine/:eid/:mid', - component: WrongLocationComponent, - data: { - cause: 'machine', - }, - title: 'EXAM - wrong machine', - }, - { - path: 'exams', - component: ExamSearchComponent, - title: 'EXAM - search', - }, - { - path: 'exams/collaborative', - component: CollaborativeExamSearchComponent, - title: 'EXAM - search', - }, - { - path: 'participations', - component: ExamParticipationsComponent, - title: 'EXAM - participations', - }, - { - path: 'participations/collaborative', - component: CollaborativeParticipationsComponent, - title: 'EXAM - participations', - }, - { - path: 'examination/logout', - component: ExaminationLogoutComponent, - title: 'EXAM - logout', - }, - { - path: 'enrolments/:id', - component: ExamEnrolmentsComponent, - title: ExamEnrolmentTitleResolverService, - }, - { - path: 'calendar/:id', - component: CalendarComponent, - data: { - isExternal: false, - isCollaborative: false, - }, - title: CalendarTitleResolverService, - }, - { - path: 'calendar/:id/external', - component: CalendarComponent, - data: { isExternal: true }, - title: 'EXAM - calendar', - }, - { - path: 'calendar/:id/collaborative', - component: CalendarComponent, - data: { isExternal: false, isCollaborative: true }, - title: 'EXAM - calendar', - }, - /* - { // this does not work apparently because admin code uses some of calendar dependencies -- path: 'calendar', -- loadChildren: () => import('./calendar/calendar.module').then((mod) => mod.CalendarModule), -- }, - */ - { - path: 'staff', - loadChildren: () => import('./dashboard/staff/staff-dashboard.module').then((mod) => mod.StaffDashboardModule), - }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes, { enableTracing: false })], - exports: [RouterModule], -}) -export class AppRoutingModule {} diff --git a/ui/src/app/app.component.spec.ts b/ui/src/app/app.component.spec.ts index d4fec5aa09..e37c8f5553 100644 --- a/ui/src/app/app.component.spec.ts +++ b/ui/src/app/app.component.spec.ts @@ -4,7 +4,7 @@ import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [AppComponent], + imports: [AppComponent], }).compileComponents(); }); diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index 497d0f1f43..b223e3add8 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -12,31 +12,64 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ -import { registerLocaleData } from '@angular/common'; +import { NgClass, registerLocaleData } from '@angular/common'; import localeEn from '@angular/common/locales/en'; import localeFi from '@angular/common/locales/fi'; import localeSv from '@angular/common/locales/sv'; import { Component, OnDestroy, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; +import { Router, RouterOutlet } from '@angular/router'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { ExaminationStatusService } from './examination/examination-status.service'; +import { NavigationComponent } from './navigation/navigation.component'; +import { DevLoginComponent } from './session/dev/dev-login.component'; import type { User } from './session/session.service'; import { SessionService } from './session/session.service'; @Component({ selector: 'xm-app', template: ` -
- -
-
- -
- -
-
+ @if (!user && devLoginRequired) { +
+ +
+ } + @if (user) { +
+ +
+ +
+
+ } `, + styles: [ + ` + #mainView { + width: auto !important; + @media print { + margin: 0 15px; + max-width: 1000px; + } + } + .vmenu-on { + width: auto; + margin-left: 17.025em !important; + + @media (max-width: 920px) { + margin-left: 0 !important; + padding-left: 0; + padding-right: 0; + } + + @media print { + overflow-x: visible; + } + } + `, + ], + standalone: true, + imports: [DevLoginComponent, NavigationComponent, NgClass, RouterOutlet], }) export class AppComponent implements OnInit, OnDestroy { user?: User; diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts deleted file mode 100644 index 38048c314a..0000000000 --- a/ui/src/app/app.module.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017 Exam Consortium - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ -import { CommonModule } from '@angular/common'; -import { HttpClient, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; -import { LOCALE_ID, NgModule } from '@angular/core'; -import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; -import { ToastrModule } from 'ngx-toastr'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { CalendarModule } from './calendar/calendar.module'; -import { StudentDashboardModule } from './dashboard/student/student-dashboard.module'; -import { EnrolmentModule } from './enrolment/enrolment.module'; -import { ExaminationModule } from './examination/examination.module'; -import { AuthInterceptor } from './interceptors/auth-interceptor'; -import { ErrorInterceptor } from './interceptors/error-interceptor'; -import { ExaminationInterceptor } from './interceptors/examination-interceptor'; -import { NavigationModule } from './navigation/navigation.module'; -import { SessionModule } from './session/session.module'; -import { SessionService } from './session/session.service'; -import { SharedModule } from './shared/shared.module'; - -// AoT requires an exported function for factories -export function HttpLoaderFactory(http: HttpClient) { - return new TranslateHttpLoader(http, '/assets/i18n/'); -} - -@NgModule({ - imports: [ - CommonModule, - HttpClientModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient], - }, - }), - ToastrModule.forRoot({ preventDuplicates: true }), - AppRoutingModule, - SharedModule, - SessionModule, - NavigationModule, - StudentDashboardModule, - ExaminationModule, - EnrolmentModule, - CalendarModule, - ], - declarations: [AppComponent], - providers: [ - { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, - { provide: HTTP_INTERCEPTORS, useClass: ExaminationInterceptor, multi: true }, - { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }, - { - provide: LOCALE_ID, - deps: [SessionService], - useFactory: (srv: SessionService) => srv.getLocale(), - }, - ], - bootstrap: [AppComponent], -}) -export class AppModule {} diff --git a/ui/src/app/app.routes.ts b/ui/src/app/app.routes.ts new file mode 100644 index 0000000000..9202ff9dfd --- /dev/null +++ b/ui/src/app/app.routes.ts @@ -0,0 +1,144 @@ +import { inject } from '@angular/core'; +import { Route } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { map, Observable } from 'rxjs'; +import { AppComponent } from './app.component'; +import { LogoutComponent } from './session/logout/logout.component'; + +const buildTitle = (key: string, extraPart = ''): Observable => { + const tx = inject(TranslateService); + const extra = extraPart ? ` ${extraPart}` : ''; + return tx.get(key).pipe( + map( + () => + `${tx.instant(key)}${extra} + - EXAM`, + ), + ); +}; + +export const APP_ROUTES: Route[] = [ + { + path: '', + component: AppComponent, + pathMatch: 'full', + title: 'EXAM', + }, + { + path: 'dashboard', + loadComponent: () => + import('./dashboard/student/student-dashboard.component').then((mod) => mod.StudentDashboardComponent), + title: () => buildTitle('i18n_enrolments_title'), + }, + { + path: 'logout', + component: LogoutComponent, + }, + { + path: 'exam/:hash', + data: { + isPreview: false, + }, + loadComponent: () => import('./examination/examination.component').then((mod) => mod.ExaminationComponent), + title: () => buildTitle('i18n_examination_title'), + }, + { + path: 'waitingroom/:id/:hash', + loadComponent: () => + import('./enrolment/waiting-room/waiting-room.component').then((mod) => mod.WaitingRoomComponent), + title: () => buildTitle('i18n_waiting_room_title'), + }, + { + path: 'waitingroom', + loadComponent: () => + import('./enrolment/waiting-room/waiting-room.component').then((mod) => mod.WaitingRoomComponent), + title: () => buildTitle('i18n_waiting_room_title'), + }, + { + path: 'wrongroom/:eid/:mid', + loadComponent: () => + import('./enrolment/wrong-location/wrong-location.component').then((mod) => mod.WrongLocationComponent), + data: { + cause: 'room', + }, + title: () => buildTitle('i18n_wrong_room_title'), + }, + { + path: 'wrongmachine/:eid/:mid', + loadComponent: () => + import('./enrolment/wrong-location/wrong-location.component').then((mod) => mod.WrongLocationComponent), + data: { + cause: 'machine', + }, + title: () => buildTitle('i18n_wrong_machine_title'), + }, + { + path: 'exams', + loadComponent: () => import('./enrolment/search/exam-search.component').then((mod) => mod.ExamSearchComponent), + title: () => buildTitle('i18n_exams_title'), + }, + { + path: 'exams/collaborative', + loadComponent: () => + import('./enrolment/search/collaborative-exam-search.component').then( + (mod) => mod.CollaborativeExamSearchComponent, + ), + title: () => buildTitle('i18n_collaborative_exams_title'), + }, + { + path: 'participations', + loadComponent: () => + import('./enrolment/finished/exam-participations.component').then((mod) => mod.ExamParticipationsComponent), + title: () => buildTitle('i18n_participations_title'), + }, + { + path: 'participations/collaborative', + loadComponent: () => + import('./enrolment/finished/collaborative-exam-participations.component').then( + (mod) => mod.CollaborativeParticipationsComponent, + ), + title: () => buildTitle('i18n_collaborative_participations_title'), + }, + { + path: 'examination/logout', + loadComponent: () => + import('./examination/logout/examination-logout.component').then((mod) => mod.ExaminationLogoutComponent), + title: () => buildTitle('i18n_examination_logout_title'), + }, + { + path: 'enrolments/:id', + loadComponent: () => + import('./enrolment/exams/exam-enrolments.component').then((mod) => mod.ExamEnrolmentsComponent), + title: (route) => buildTitle('i18n_enrolment_title', `#${route.params.id}`), + }, + { + path: 'calendar/:id', + loadComponent: () => import('./calendar/calendar.component').then((mod) => mod.CalendarComponent), + data: { + isExternal: false, + isCollaborative: false, + }, + title: (route) => buildTitle('i18n_reservation_title', `#${route.params.id}`), + }, + { + path: 'calendar/:id/external', + loadComponent: () => import('./calendar/calendar.component').then((mod) => mod.CalendarComponent), + data: { + isExternal: true, + }, + title: (route) => buildTitle('i18n_external_reservation_title', `#${route.params.id}`), + }, + { + path: 'calendar/:id/collaborative', + loadComponent: () => import('./calendar/calendar.component').then((mod) => mod.CalendarComponent), + data: { + isExternal: false, + isCollaborative: true, + }, + title: (route) => buildTitle('i18n_collaborative_reservation_title', `#${route.params.id}`), + }, + { + path: 'staff', + loadChildren: () => import('./dashboard/staff/staff.routes').then((mod) => mod.STAFF_ROUTES), + }, +]; diff --git a/ui/src/app/calendar/booking-calendar.component.ts b/ui/src/app/calendar/booking-calendar.component.ts index 4efec93594..4995a5625f 100644 --- a/ui/src/app/calendar/booking-calendar.component.ts +++ b/ui/src/app/calendar/booking-calendar.component.ts @@ -12,6 +12,7 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ + import { AfterViewInit, ChangeDetectionStrategy, @@ -23,8 +24,9 @@ import { Output, SimpleChanges, ViewChild, + signal, } from '@angular/core'; -import { FullCalendarComponent } from '@fullcalendar/angular'; +import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular'; import { CalendarOptions, EventApi, EventClickArg, EventInput } from '@fullcalendar/core'; import enLocale from '@fullcalendar/core/locales/en-gb'; import fiLocale from '@fullcalendar/core/locales/fi'; @@ -33,21 +35,27 @@ import luxon2Plugin from '@fullcalendar/luxon2'; import timeGridPlugin from '@fullcalendar/timegrid'; import { TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; -import type { Accessibility, ExamRoom } from '../reservation/reservation.model'; +import type { Accessibility, ExamRoom } from 'src/app/reservation/reservation.model'; import { CalendarService } from './calendar.service'; @Component({ selector: 'xm-booking-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: ` -
-
-
- + @if (visible) { +
+
+ @if (visible) { +
+ +
+ }
-
+ } `, + standalone: true, + imports: [FullCalendarModule], }) export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewInit { @Output() eventSelected = new EventEmitter(); @@ -65,10 +73,15 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni @ViewChild('fc') calendar!: FullCalendarComponent; - calendarOptions: CalendarOptions; + calendarOptions = signal({}); + searchStart = DateTime.now().startOf('week').toISO(); + searchEnd = DateTime.now().endOf('week').toISO(); - constructor(private translate: TranslateService, private Calendar: CalendarService) { - this.calendarOptions = { + constructor( + private translate: TranslateService, + private Calendar: CalendarService, + ) { + this.calendarOptions.set({ plugins: [luxon2Plugin, timeGridPlugin], initialView: 'timeGridWeek', firstDay: 1, @@ -82,17 +95,15 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni eventMinHeight: 45, events: this.refetch, eventClick: this.eventClicked.bind(this), - }; - this.translate.onLangChange.subscribe((event) => { - this.calendarOptions = { ...this.calendarOptions, locale: event.lang }; - //this.calendar.getApi().destroy(); - //this.calendar.getApi().render(); }); + this.translate.onLangChange.subscribe((event) => + this.calendarOptions.set({ ...this.calendarOptions(), locale: event.lang }), + ); } ngOnInit() { if (this.minDate && this.maxDate) { - this.calendarOptions.validRange = { + this.calendarOptions().validRange = { end: DateTime.fromJSDate(this.maxDate).endOf('week').plus({ hours: 1 }).toFormat('yyyy-MM-dd'), start: DateTime.fromJSDate(this.minDate).startOf('week').toFormat('yyyy-MM-dd'), }; @@ -107,28 +118,45 @@ export class BookingCalendarComponent implements OnInit, OnChanges, AfterViewIni ngOnChanges(changes: SimpleChanges) { if (changes.room && this.room) { - const earliestOpening = this.Calendar.getEarliestOpening(this.room); + const earliestOpening = this.Calendar.getEarliestOpening(this.room, this.searchStart, this.searchEnd); const minTime = earliestOpening.getHours() > 1 ? DateTime.fromJSDate(earliestOpening).minus({ hour: 1 }).toJSDate() : earliestOpening; - const latestClosing = this.Calendar.getLatestClosing(this.room); + const latestClosing = this.Calendar.getLatestClosing(this.room, this.searchStart, this.searchEnd); const maxTime = latestClosing.getHours() < 23 ? DateTime.fromJSDate(latestClosing).plus({ hour: 1 }).toJSDate() : latestClosing; - this.calendarOptions.hiddenDays = this.Calendar.getClosedWeekdays(this.room); - this.calendarOptions.slotMinTime = DateTime.fromJSDate(minTime).toFormat('HH:mm:ss'); - this.calendarOptions.slotMaxTime = DateTime.fromJSDate(maxTime).toFormat('HH:mm:ss'); - this.calendarOptions.timeZone = this.room.localTimezone; + this.calendarOptions.update((cos) => ({ + ...cos, + hiddenDays: this.Calendar.getClosedWeekdays(this.room, this.searchStart, this.searchEnd), + slotMinTime: DateTime.fromJSDate(minTime).toFormat('HH:mm:ss'), + slotMaxTime: DateTime.fromJSDate(maxTime).toFormat('HH:mm:ss'), + timeZone: this.room.localTimezone, + })); if (this.calendar) this.calendar.getApi().refetchEvents(); } if (changes.accessibilities && this.calendar) { this.calendar.getApi().refetchEvents(); } } - refetch = (input: { startStr: string; timeZone: string }, success: (events: EventInput[]) => void) => + + refetch = (input: { startStr: string; timeZone: string }, success: (events: EventInput[]) => void) => { + this.searchStart = input.startStr; + this.searchEnd = DateTime.fromISO(input.startStr).endOf('week').toISO() as string; + const hidden = this.Calendar.getClosedWeekdays(this.room, this.searchStart, this.searchEnd); + const earliestOpening = this.Calendar.getEarliestOpening(this.room, this.searchStart, this.searchEnd); + const latestClosing = this.Calendar.getLatestClosing(this.room, this.searchStart, this.searchEnd); + this.calendarOptions.update((cos) => ({ + ...cos, + hiddenDays: hidden, + slotMinTime: DateTime.fromJSDate(earliestOpening).toFormat('HH:mm:ss'), + slotMaxTime: DateTime.fromJSDate(latestClosing).toFormat('HH:mm:ss'), + })); + this.moreEventsNeeded.emit({ date: input.startStr, timeZone: input.timeZone, success: success }); + }; eventClicked(arg: EventClickArg): void { if (arg.event.extendedProps?.availableMachines > 0) { diff --git a/ui/src/app/calendar/calendar.component.html b/ui/src/app/calendar/calendar.component.html index 9e12a665f8..5e7d9cf3fc 100644 --- a/ui/src/app/calendar/calendar.component.html +++ b/ui/src/app/calendar/calendar.component.html @@ -1,62 +1,74 @@ -
-
-
- -

{{ 'sitnet_calendar' | translate }}

-
-
- + + + - + @if (examInfo && reservationWindowSize) { +
+
+ +
+
+ } -
- -
+ @if (examInfo && hasOptionalSections()) { +
+
+ +
+
+ } -
- -
+ @if (isInteroperable && isExternal) { +
+
+ +
+
+ } -
- - +
+
+ + +
-
-
-
+
+
+
- +

- {{ getSequenceNumber('confirmation') }}. {{ 'sitnet_calendar_phase_3' | translate }} + {{ getSequenceNumber('confirmation') }}. {{ 'i18n_calendar_phase_3' | translate }}

+
+ @@ -73,20 +85,24 @@

- {{ 'sitnet_course_name' | translate }}: + {{ 'i18n_course_name' | translate }}:
-
- - {{ examInfo.course.name }} -
+ @if (examInfo.course) { +
+ @if (examInfo) { + + } + {{ examInfo.course.name }} +
+ }
- {{ 'sitnet_exam_validity' | translate }}: + {{ 'i18n_exam_validity' | translate }}:
- {{ examInfo.examActiveStartDate | date : 'dd.MM.yyyy' }} - - {{ examInfo.examActiveEndDate | date : 'dd.MM.yyyy' }} + {{ examInfo.periodStart | date: 'dd.MM.yyyy' }} - + {{ examInfo.periodEnd | date: 'dd.MM.yyyy' }}
@@ -95,13 +111,13 @@

- {{ 'sitnet_examination_location' | translate }}: + {{ 'i18n_examination_location' | translate }}:
{{ reservation?.room?.name }}
- {{ 'sitnet_reservation' | translate }}: + {{ 'i18n_reservation' | translate }}:
{{ reservation?.time }} @@ -113,7 +129,7 @@

- {{ 'sitnet_exam_duration' | translate }}: + {{ 'i18n_exam_duration' | translate }}:
{{ printExamDuration(examInfo) }} @@ -124,8 +140,8 @@

-
-
+
+
-
+
-
+ diff --git a/ui/src/app/calendar/calendar.component.scss b/ui/src/app/calendar/calendar.component.scss new file mode 100644 index 0000000000..23312debe5 --- /dev/null +++ b/ui/src/app/calendar/calendar.component.scss @@ -0,0 +1,26 @@ +@import '../shared/definitions.scss'; +.calendar-phase-title { + font-size: 22px; + color: #2c2c2c; +} + +.calendar-phase-icon { + float: right; +} + +.calendar-titles { + padding-top: 10px; +} + +.calendar-course-title { + color: #2c2c2c; + font-size: 16px; + font-weight: bold; +} + +.accs-list { + display: flex; + flex-flow: nowrap; + align-items: center; + gap: 5px; +} diff --git a/ui/src/app/calendar/calendar.component.ts b/ui/src/app/calendar/calendar.component.ts index c964311577..a067beb0bc 100644 --- a/ui/src/app/calendar/calendar.component.ts +++ b/ui/src/app/calendar/calendar.component.ts @@ -12,29 +12,55 @@ * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and limitations under the Licence. */ +import { DatePipe, NgClass } from '@angular/common'; import type { OnInit } from '@angular/core'; import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; import { ToastrService } from 'ngx-toastr'; import { switchMap, tap } from 'rxjs/operators'; -import { ExamEnrolment } from '../enrolment/enrolment.model'; -import type { Accessibility, ExamRoom } from '../reservation/reservation.model'; -import { DateTimeService } from '../shared/date/date.service'; -import { ConfirmationDialogService } from '../shared/dialogs/confirmation-dialog.service'; +import { ExamEnrolment } from 'src/app/enrolment/enrolment.model'; +import type { Accessibility, ExamRoom } from 'src/app/reservation/reservation.model'; +import { PageContentComponent } from 'src/app/shared/components/page-content.component'; +import { PageHeaderComponent } from 'src/app/shared/components/page-header.component'; +import { DateTimeService } from 'src/app/shared/date/date.service'; +import { ConfirmationDialogService } from 'src/app/shared/dialogs/confirmation-dialog.service'; +import { HistoryBackComponent } from 'src/app/shared/history/history-back.component'; +import { CourseCodeComponent } from 'src/app/shared/miscellaneous/course-code.component'; +import { AutoFocusDirective } from 'src/app/shared/select/auto-focus.directive'; import { CalendarService, ExamInfo, Organisation } from './calendar.service'; +import { CalendarExamInfoComponent } from './helpers/exam-info.component'; +import { OptionalSectionsComponent } from './helpers/optional-sections.component'; +import { OrganisationPickerComponent } from './helpers/organisation-picker.component'; +import { SlotPickerComponent } from './helpers/slot-picker.component'; @Component({ selector: 'xm-calendar', templateUrl: './calendar.component.html', + styleUrls: ['./calendar.component.scss'], + standalone: true, + imports: [ + HistoryBackComponent, + AutoFocusDirective, + CalendarExamInfoComponent, + OptionalSectionsComponent, + OrganisationPickerComponent, + SlotPickerComponent, + NgClass, + CourseCodeComponent, + DatePipe, + TranslateModule, + PageHeaderComponent, + PageContentComponent, + ], }) export class CalendarComponent implements OnInit { isInteroperable = false; confirming = false; examInfo: ExamInfo = { - examActiveStartDate: null, - examActiveEndDate: null, + periodStart: null, + periodEnd: null, name: '', duration: 0, anonymous: false, @@ -89,13 +115,12 @@ export class CalendarComponent implements OnInit { tap((resp) => { this.reservationWindowSize = resp.value; this.reservationWindowEndDate = DateTime.now().plus({ day: resp.value }).toJSDate(); - this.minDate = [new Date(), new Date(this.examInfo.examActiveStartDate as string)].reduce((a, b) => + this.minDate = [new Date(), new Date(this.examInfo.periodStart as string)].reduce((a, b) => a > b ? a : b, ); - this.maxDate = [ - this.reservationWindowEndDate, - new Date(this.examInfo.examActiveEndDate as string), - ].reduce((a, b) => (a < b ? a : b)); + this.maxDate = [this.reservationWindowEndDate, new Date(this.examInfo.periodEnd as string)].reduce( + (a, b) => (a < b ? a : b), + ); }), switchMap(() => this.Calendar.getExamVisitSupportStatus$()), tap((resp) => (this.isInteroperable = resp.isExamVisitSupported)), @@ -141,8 +166,8 @@ export class CalendarComponent implements OnInit { makeExternalReservation() { this.Dialog.open$( - this.translate.instant('sitnet_confirm'), - this.translate.instant('sitnet_confirm_external_reservation'), + this.translate.instant('i18n_confirm'), + this.translate.instant('i18n_confirm_external_reservation'), ).subscribe({ next: () => this.router.navigate(['/calendar', this.examId, 'external'], { @@ -196,7 +221,7 @@ export class CalendarComponent implements OnInit { } const selectedSectionIds = this.examInfo.examSections.filter((es) => es.selected).map((es) => es.id); if (!this.sectionSelectionOk()) { - this.toast.error(this.translate.instant('sitnet_select_at_least_one_section')); + this.toast.error(this.translate.instant('i18n_select_at_least_one_section')); return; } this.confirming = true; diff --git a/ui/src/app/calendar/calendar.module.ts b/ui/src/app/calendar/calendar.module.ts deleted file mode 100644 index 2faa32beb2..0000000000 --- a/ui/src/app/calendar/calendar.module.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2018 Exam Consortium - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { FullCalendarModule } from '@fullcalendar/angular'; -import { NgbCollapseModule, NgbDropdownModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; -import { SharedModule } from '../shared/shared.module'; -import { BookingCalendarComponent } from './booking-calendar.component'; -import { CalendarTitleResolverService } from './calendar-title-resolver.service'; -import { CalendarComponent } from './calendar.component'; -import { CalendarService } from './calendar.service'; -import { CalendarExamInfoComponent } from './helpers/exam-info.component'; -import { OptionalSectionsComponent } from './helpers/optional-sections.component'; -import { OrganisationPickerComponent } from './helpers/organisation-picker.component'; -import { SelectedRoomComponent } from './helpers/selected-room.component'; -import { SlotPickerComponent } from './helpers/slot-picker.component'; - -@NgModule({ - imports: [FullCalendarModule, RouterModule, NgbPopoverModule, NgbDropdownModule, NgbCollapseModule, SharedModule], - declarations: [ - BookingCalendarComponent, - CalendarComponent, - CalendarExamInfoComponent, - OptionalSectionsComponent, - OrganisationPickerComponent, - SlotPickerComponent, - SelectedRoomComponent, - ], - providers: [CalendarService, CalendarTitleResolverService], - exports: [CalendarComponent, BookingCalendarComponent], -}) -export class CalendarModule {} diff --git a/ui/src/app/calendar/calendar.service.ts b/ui/src/app/calendar/calendar.service.ts index 60d36a9bf4..6b41b480b1 100644 --- a/ui/src/app/calendar/calendar.service.ts +++ b/ui/src/app/calendar/calendar.service.ts @@ -14,18 +14,18 @@ */ import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { DateTime } from 'luxon'; +import { DateTime, Interval } from 'luxon'; import type { Observable } from 'rxjs'; -import { ExamEnrolment } from '../enrolment/enrolment.model'; -import { Course, Exam, ExamSection, MaintenancePeriod } from '../exam/exam.model'; +import { ExamEnrolment } from 'src/app/enrolment/enrolment.model'; +import { Course, Exam, ExamSection, MaintenancePeriod } from 'src/app/exam/exam.model'; import type { Accessibility, DefaultWorkingHours, ExamRoom, ExceptionWorkingHours, -} from '../reservation/reservation.model'; -import { SessionService } from '../session/session.service'; -import { DateTimeService } from '../shared/date/date.service'; +} from 'src/app/reservation/reservation.model'; +import { SessionService } from 'src/app/session/session.service'; +import { DateTimeService } from 'src/app/shared/date/date.service'; type WeekdayNames = Record; @@ -68,7 +68,7 @@ export class CalendarService { constructor( private http: HttpClient, - private DateTime: DateTimeService, + private DateTimeService: DateTimeService, private Session: SessionService, ) {} @@ -101,7 +101,7 @@ export class CalendarService { const lang = this.Session.getUser().lang; const locale = lang.toLowerCase() + '-' + lang.toUpperCase(); const options: Intl.DateTimeFormatOptions = { weekday: 'short' }; - const weekday = this.DateTime.getDateForWeekday; + const weekday = this.DateTimeService.getDateForWeekday; return { SUNDAY: { ord: 7, name: weekday(0).toLocaleDateString(locale, options) }, MONDAY: { ord: 1, name: weekday(1).toLocaleDateString(locale, options) }, @@ -163,30 +163,51 @@ export class CalendarService { return room.calendarExceptionEvents.map((e) => this.formatExceptionEvent(e, room.localTimezone)); } - getEarliestOpening(room: ExamRoom): Date { + getEarliestOpening(room: ExamRoom, start: string, end: string): Date { + // if we have an extra opening that spans midnight then it's 24h + if (this.hasMultiDayExceptionalOpeningDuring(room.calendarExceptionEvents, start, end)) { + return DateTime.now().startOf('day').toJSDate(); + } const tz = room.localTimezone; - const openings = room.defaultWorkingHours.map((dwh) => { - const start = DateTime.fromISO(dwh.startTime, { zone: tz }); - return DateTime.now().set({ hour: start.hour, minute: start.minute, second: start.second }); - }); - return DateTime.min(...openings) - .set({ minute: 0 }) - .toJSDate(); + const regularOpenings = room.defaultWorkingHours.map((dwh) => + this.normalize(DateTime.fromISO(dwh.startTime, { zone: tz })), + ); + const extraOpenings = room.calendarExceptionEvents + .filter((e) => !e.outOfService && e.startDate >= start && e.endDate <= end) + .flatMap((d) => this.daysBetween(DateTime.fromISO(d.startDate), DateTime.fromISO(d.endDate))) + .map((d) => this.normalize(d.start as DateTime)); + + return DateTime.min(...regularOpenings.concat(extraOpenings)).toJSDate(); } - getLatestClosing(room: ExamRoom): Date { + getLatestClosing(room: ExamRoom, start: string, end: string): Date { + // if we have an extra opening that spans midnight then it's 24h + if (this.hasMultiDayExceptionalOpeningDuring(room.calendarExceptionEvents, start, end)) { + return DateTime.now().endOf('day').toJSDate(); + } const tz = room.localTimezone; - const closings = room.defaultWorkingHours.map((dwh) => { - const end = DateTime.fromISO(dwh.endTime, { zone: tz }); - return DateTime.now().set({ hour: end.hour, minute: end.minute, second: end.second }); - }); - return DateTime.max(...closings).toJSDate(); + const regularClosings = room.defaultWorkingHours.map((dwh) => + this.normalize(DateTime.fromISO(dwh.endTime, { zone: tz })), + ); + const extraClosings = room.calendarExceptionEvents + .filter((e) => !e.outOfService && e.startDate >= start && e.endDate <= end) + .flatMap((d) => this.daysBetween(DateTime.fromISO(d.startDate), DateTime.fromISO(d.endDate))) + .map((d) => this.normalize(d.end as DateTime)); + + return DateTime.max(...regularClosings.concat(extraClosings)).toJSDate(); } - getClosedWeekdays(room: ExamRoom): number[] { + getClosedWeekdays(room: ExamRoom, start: string, end: string): number[] { const weekdays = ['SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY']; - const openedDays = room.defaultWorkingHours.map((dwh) => weekdays.indexOf(dwh.weekday)); - return [0, 1, 2, 3, 4, 5, 6].filter((x) => openedDays.indexOf(x) === -1); + const regularDays = room.defaultWorkingHours.map((d) => weekdays.indexOf(d.weekday)); + const extraDays = room.calendarExceptionEvents + .filter((e) => !e.outOfService && this.weeksOverlap(e.startDate, e.endDate, start, end)) + .flatMap((d) => this.daysBetween(DateTime.fromISO(d.startDate), DateTime.fromISO(d.endDate))) + .map((d) => (d.start?.weekday === 7 ? 0 : (d.start as DateTime).weekday)); // locale nuisances + const closedDays = new Set( + [0, 1, 2, 3, 4, 5, 6].filter((x) => regularDays.concat(extraDays).indexOf(x) === -1), + ); + return Array.from(closedDays); } listRooms$ = () => this.http.get('/app/rooms'); @@ -211,10 +232,20 @@ export class CalendarService { getExamInfo$ = (collaborative: boolean, id: number) => this.http.get(collaborative ? `/app/iop/exams/${id}/info` : `/app/student/exam/${id}/info`); + private daysBetween = (start: DateTime, end: DateTime) => Interval.fromDateTimes(start, end).splitBy({ day: 1 }); + private normalize = (d: DateTime) => DateTime.now().set({ hour: d.hour, minute: d.minute, second: d.second }); private adjustBack(date: DateTime): string { const offset = date.isInDST ? 1 : 0; return date.toUTC().plus({ hour: offset }).toISO() as string; } + private weeksOverlap = (w1d1: string, w1d2: string, w2d1: string, w2d2: string) => + DateTime.fromISO(w1d1).weekNumber <= DateTime.fromISO(w2d1).weekNumber && + DateTime.fromISO(w1d2).weekNumber >= DateTime.fromISO(w2d2).weekNumber; + + private hasMultiDayExceptionalOpeningDuring = (exceptions: ExceptionWorkingHours[], start: string, end: string) => + exceptions + .filter((e) => !e.outOfService && this.weeksOverlap(e.startDate, e.endDate, start, end)) + .some((e) => DateTime.fromISO(e.startDate).ordinal !== DateTime.fromISO(e.endDate).ordinal); private reserveInternal$ = (slot: Slot, accs: Accessibility[], collaborative: boolean): Observable => { slot.aids = accs.map((item) => item.id); @@ -240,7 +271,7 @@ export class CalendarService { ...event, start: startDate.toFormat('dd.MM.yyyy HH:mm'), end: endDate.toFormat('dd.MM.yyyy HH:mm'), - description: event.outOfService ? 'sitnet_closed' : 'sitnet_open', + description: event.outOfService ? 'i18n_closed' : 'i18n_open', }; } } diff --git a/ui/src/app/calendar/helpers/accessibility-picker.component.ts b/ui/src/app/calendar/helpers/accessibility-picker.component.ts new file mode 100644 index 0000000000..da46de33d5 --- /dev/null +++ b/ui/src/app/calendar/helpers/accessibility-picker.component.ts @@ -0,0 +1,73 @@ +import { Component, EventEmitter, Input, Output, signal } from '@angular/core'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import { FilterableAccessibility } from './slot-picker.component'; + +@Component({ + selector: 'xm-calendar-accessibility-picker', + template: `
+
+
+
+ @if (!disabled) { + + } @else { + + {{ 'i18n_calendar_room_accessibility_info' | translate }} + + } +
+
+
+
+ {{ 'i18n_exam_room_accessibility' | translate }} +
+
+
+
+
+ @for (item of items; track item.id) { + + + {{ item.name }} + + } +
+
+
+
+
+
+
`, + styleUrls: ['../calendar.component.scss'], + standalone: true, + imports: [NgbCollapse, TranslateModule], +}) +export class AccessibilityPickerComponent { + @Input() items: FilterableAccessibility[] = []; + @Input() disabled = false; + @Output() itemsChange = new EventEmitter(); + + showMenu = signal(false); + + select = () => this.itemsChange.emit(this.items); +} diff --git a/ui/src/app/calendar/helpers/exam-info.component.ts b/ui/src/app/calendar/helpers/exam-info.component.ts index 2ca804ccd3..5b3f106357 100644 --- a/ui/src/app/calendar/helpers/exam-info.component.ts +++ b/ui/src/app/calendar/helpers/exam-info.component.ts @@ -1,52 +1,63 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { DatePipe } from '@angular/common'; +import { Component, Input, OnInit, computed, signal } from '@angular/core'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; -import { DateTimeService } from '../../shared/date/date.service'; -import type { ExamInfo } from '../calendar.service'; +import type { ExamInfo } from 'src/app/calendar/calendar.service'; +import { DateTimeService } from 'src/app/shared/date/date.service'; +import { MathJaxDirective } from 'src/app/shared/math/math-jax.directive'; +import { CourseCodeComponent } from 'src/app/shared/miscellaneous/course-code.component'; @Component({ selector: 'xm-calendar-exam-info', template: ` -
+
-
- -

1. {{ 'sitnet_calendar_phase_1' | translate }}

- - - -
+
+
+

1. {{ 'i18n_calendar_phase_1' | translate }}

+
+
+ +
{{ examInfo.name }} - ({{ 'sitnet_anonymous_review' | translate }}) + @if (examInfo.anonymous) { + ({{ 'i18n_anonymous_review' | translate }}) + }
-
+
-
{{ 'sitnet_course_name' | translate }}:
+
{{ 'i18n_course_name' | translate }}:
-
- - {{ examInfo.course.name }} -
+ @if (!collaborative) { +
+ + {{ examInfo.course.name }} +
+ }
- {{ 'sitnet_exam_validity' | translate }}: + {{ 'i18n_exam_validity' | translate }}:
- {{ examInfo.examActiveStartDate | date : 'dd.MM.yyyy' }} - - {{ examInfo.examActiveEndDate | date : 'dd.MM.yyyy' }} + {{ examInfo.periodStart | date: 'dd.MM.yyyy' }} - + {{ examInfo.periodEnd | date: 'dd.MM.yyyy' }}
-
- {{ 'sitnet_exam_duration' | translate }}: +
+ {{ 'i18n_exam_duration' | translate }}:
{{ printExamDuration(examInfo) }} @@ -54,51 +65,59 @@ import type { ExamInfo } from '../calendar.service';
-
+
- - {{ 'sitnet_calendar_instructions' | translate }}: + + {{ 'i18n_calendar_instructions' | translate }}:
-
+
- - - {{ getReservationWindowDescription() }} - + @if (showReservationWindowDescription()) { + + + {{ reservationWindowDescription() }} + + }
`, + styleUrls: ['../calendar.component.scss'], + standalone: true, + imports: [CourseCodeComponent, MathJaxDirective, DatePipe, TranslateModule], }) export class CalendarExamInfoComponent implements OnInit { @Input() examInfo!: ExamInfo; @Input() reservationWindowSize = 0; @Input() collaborative = false; - reservationWindowEndDate = new Date(); + reservationWindowEndDate = signal(new Date()); + reservationWindowDescription = computed(() => { + const text = this.translate + .instant('i18n_description_reservation_window') + .replace('{}', this.reservationWindowSize.toString()); + return `${text} (${DateTime.fromJSDate(this.reservationWindowEndDate()).toFormat('dd.MM.yyyy')})`; + }); + showReservationWindowDescription = computed( + () => + !!this.reservationWindowEndDate && + DateTime.fromISO(this.examInfo.periodEnd as string).toJSDate() > this.reservationWindowEndDate(), + ); - constructor(private translate: TranslateService, private DateTimeService: DateTimeService) {} + constructor( + private translate: TranslateService, + private DateTimeService: DateTimeService, + ) {} ngOnInit() { - this.reservationWindowEndDate = DateTime.fromJSDate(this.reservationWindowEndDate) - .plus({ day: this.reservationWindowSize }) - .toJSDate(); + this.reservationWindowEndDate.set( + DateTime.fromJSDate(this.reservationWindowEndDate()).plus({ day: this.reservationWindowSize }).toJSDate(), + ); } printExamDuration = (exam: { duration: number }) => this.DateTimeService.printExamDuration(exam); - - getReservationWindowDescription(): string { - const text = this.translate - .instant('sitnet_description_reservation_window') - .replace('{}', this.reservationWindowSize.toString()); - return `${text} (${DateTime.fromJSDate(this.reservationWindowEndDate).toFormat('dd.MM.yyyy')})`; - } - - showReservationWindowInfo = (): boolean => - !!this.reservationWindowEndDate && - DateTime.fromISO(this.examInfo.examActiveEndDate as string).toJSDate() > this.reservationWindowEndDate; } diff --git a/ui/src/app/calendar/helpers/optional-sections.component.ts b/ui/src/app/calendar/helpers/optional-sections.component.ts index a934b0e2ab..6a73536fdf 100644 --- a/ui/src/app/calendar/helpers/optional-sections.component.ts +++ b/ui/src/app/calendar/helpers/optional-sections.component.ts @@ -1,74 +1,95 @@ +import { NgClass, UpperCasePipe } from '@angular/common'; import { Component, EventEmitter, Input, Output } from '@angular/core'; -import type { ExamInfo } from '../calendar.service'; +import { FormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; +import type { ExamInfo } from 'src/app/calendar/calendar.service'; @Component({ selector: 'xm-calendar-optional-sections', template: ` -
-
- -

2. {{ 'sitnet_exam_materials' | translate }}

- +
+ +

2. {{ 'i18n_exam_materials' | translate }}

+ @if (sectionSelectionOk()) { + -
-
-
-
-
-
-
- {{ 'sitnet_exam_section' | translate }}: {{ section.name }} -
-
-
- {{ 'sitnet_optional_section' | translate | uppercase }} + } + + @for (section of examInfo.examSections; track section.id) { +
+
+
+
+
+ {{ 'i18n_exam_section' | translate }}: {{ section.name }} +
+
+ @if (section.optional) { +
+ {{ 'i18n_optional_section' | translate | uppercase }} +
+ }
-
-
-
-
-
- {{ section.description }} -
-
-
- - +
+
+
+
+ {{ section.description }} +
+
+ @if (section.optional) { +
+ + +
+ }
+ @if (section.examMaterials.length > 0) { +
+
+ {{ 'i18n_exam_materials' | translate }} +
+
+ } + @for (material of section.examMaterials; track material.id) { +
+ + {{ 'i18n_name' | translate | uppercase }}: {{ material.name }} + @if (material.author) { + {{ 'i18n_author' | translate | uppercase }}: {{ material.author }} + } + @if (material.isbn) { + ISBN: {{ material.isbn }} + } + +
+ }
-
-
- {{ 'sitnet_exam_materials' | translate }} -
-
-
- - {{ 'sitnet_name' | translate | uppercase }}: {{ material.name }} - - {{ 'sitnet_author' | translate | uppercase }}: {{ material.author }} - - ISBN: {{ material.isbn }} - -
-
+ }
`, + styleUrls: ['../calendar.component.scss'], + standalone: true, + imports: [NgClass, FormsModule, UpperCasePipe, TranslateModule], }) export class OptionalSectionsComponent { @Input() examInfo!: ExamInfo; diff --git a/ui/src/app/calendar/helpers/organisation-picker.component.ts b/ui/src/app/calendar/helpers/organisation-picker.component.ts index f7844e9249..8de834809c 100644 --- a/ui/src/app/calendar/helpers/organisation-picker.component.ts +++ b/ui/src/app/calendar/helpers/organisation-picker.component.ts @@ -1,57 +1,66 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import type { Organisation } from '../calendar.service'; -import { CalendarService } from '../calendar.service'; +import { NgClass } from '@angular/common'; +import { Component, EventEmitter, Input, OnInit, Output, signal } from '@angular/core'; +import { NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule } from '@ngx-translate/core'; +import type { Organisation } from 'src/app/calendar/calendar.service'; +import { CalendarService } from 'src/app/calendar/calendar.service'; @Component({ selector: 'xm-calendar-organisation-picker', template: ` -
+

- {{ sequenceNumber }}. {{ 'sitnet_choose_institution' | translate }} + {{ sequenceNumber }}. {{ 'i18n_choose_institution' | translate }}

- - - + @if (selectedOrganisation()) { + + + + }
-
+
-
@@ -59,16 +68,23 @@ import { CalendarService } from '../calendar.service';
-
-
-
- {{ selectedOrganisation?.name }} ({{ selectedOrganisation?.code }}) + @if (selectedOrganisation()) { +
+
+
+ {{ selectedOrganisation()?.name }} ({{ selectedOrganisation()?.code }}) +
-
+ }
`, + styleUrls: ['../calendar.component.scss'], + standalone: true, + imports: [NgClass, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem, TranslateModule], }) export class OrganisationPickerComponent implements OnInit { @Input() sequenceNumber = 0; @@ -76,21 +92,22 @@ export class OrganisationPickerComponent implements OnInit { @Output() selected = new EventEmitter(); @Output() cancelled = new EventEmitter(); - organisations: Organisation[] = []; - selectedOrganisation?: Organisation; + organisations = signal([]); + selectedOrganisation = signal(undefined); constructor(private Calendar: CalendarService) {} ngOnInit() { - this.Calendar.listOrganisations$().subscribe( - (resp) => (this.organisations = resp.filter((org) => !org.homeOrg && org.facilities.length > 0)), + this.Calendar.listOrganisations$().subscribe((resp) => + this.organisations.set(resp.filter((org) => !org.homeOrg && org.facilities.length > 0)), ); } setOrganisation = (organisation: Organisation) => { - this.organisations.forEach((o) => (o.filtered = false)); - organisation.filtered = true; - this.selectedOrganisation = organisation; + const orgs = this.organisations().map((o) => ({ ...o, filtered: false })); + const i = this.organisations().findIndex((o) => o._id === organisation._id); + this.organisations.set(orgs.splice(i, 1, { ...orgs[i], filtered: true })); + this.selectedOrganisation.set({ ...organisation, filtered: true }); this.selected.emit(organisation); }; diff --git a/ui/src/app/calendar/helpers/selected-room.component.ts b/ui/src/app/calendar/helpers/selected-room.component.ts index fb7984898f..8042df42e3 100644 --- a/ui/src/app/calendar/helpers/selected-room.component.ts +++ b/ui/src/app/calendar/helpers/selected-room.component.ts @@ -1,17 +1,20 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; +import { DatePipe, NgClass, UpperCasePipe } from '@angular/common'; +import { Component, Input, OnChanges, OnInit, signal } from '@angular/core'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; -import { MaintenancePeriod } from '../../exam/exam.model'; -import type { ExamRoom, ExceptionWorkingHours } from '../../reservation/reservation.model'; -import type { OpeningHours } from '../calendar.service'; -import { CalendarService } from '../calendar.service'; +import type { OpeningHours } from 'src/app/calendar/calendar.service'; +import { CalendarService } from 'src/app/calendar/calendar.service'; +import { MaintenancePeriod } from 'src/app/exam/exam.model'; +import type { ExamRoom, ExceptionWorkingHours } from 'src/app/reservation/reservation.model'; +import { OrderByPipe } from 'src/app/shared/sorting/order-by.pipe'; @Component({ selector: 'xm-calendar-selected-room', template: `
-
- {{ room.name }} +
+ {{ room.name }}
{{ room.mailAddress.street }} {{ room.mailAddress.zip }} @@ -20,64 +23,93 @@ import { CalendarService } from '../calendar.service';
-
{{ 'sitnet_room_default_working_hours' | translate }}
+
{{ 'i18n_room_default_working_hours' | translate }}
({{ room.localTimezone }})
-
-
{{ oh.name | uppercase }}
-
{{ oh.periodText }}
-
+ @for (oh of openingHours(); track oh.ord) { +
+
{{ oh.name | uppercase }}
+
{{ oh.periodText }}
+
+ }
-
-
{{ 'sitnet_maintenance_periods' | translate }}:
-
-
- {{ period.startsAt | date : 'dd.MM.yyyy HH:mm' }} - {{ period.endsAt | date : 'dd.MM.yyyy HH:mm' }} - {{ period.description }} + @if (thisWeeksMaintenancePeriods().length > 0) { +
+
{{ 'i18n_maintenance_periods' | translate }}:
+
+ @for (period of thisWeeksMaintenancePeriods() | orderBy: 'startsAt'; track period.id) { +
+ {{ period.startsAt | date: 'dd.MM.yyyy HH:mm' }} - + {{ period.endsAt | date: 'dd.MM.yyyy HH:mm' }} + {{ period.description }} +
+ }
-
-
-
{{ 'sitnet_exception_datetimes' | translate }}:
-
-
- {{ eh.start }} - {{ eh.end }} + } @else { +
+
{{ 'i18n_no_maintenance_periods_this_week' | translate }}
+
+ } + @if (exceptionHours().length > 0) { +
+
{{ 'i18n_exception_datetimes' | translate }}:
+
+ @for (eh of exceptionHours(); track eh.id) { +
+ {{ eh.start }} - {{ eh.end }} {{ eh.description + '' | translate }} +
+ }
-
-
-
{{ 'sitnet_instructions' | translate }}:
-
{{ getRoomInstructions() }}
-
-
-
{{ 'sitnet_room_accessibility' | translate }}:
-
{{ getRoomAccessibility() }}
-
+ } @else { +
+
{{ 'i18n_no_exceptions_this_week' | translate }}
+
+ } + @if (getRoomInstructions()) { +
+
{{ 'i18n_instructions' | translate }}:
+
{{ getRoomInstructions() }}
+
+ } + @if (getRoomAccessibility()) { +
+
{{ 'i18n_room_accessibility' | translate }}:
+
{{ getRoomAccessibility() }}
+
+ } `, + styleUrls: ['../calendar.component.scss'], + standalone: true, + imports: [NgClass, NgbPopover, UpperCasePipe, DatePipe, TranslateModule, OrderByPipe], }) export class SelectedRoomComponent implements OnInit, OnChanges { @Input() room!: ExamRoom; @Input() maintenancePeriods: MaintenancePeriod[] = []; @Input() viewStart = DateTime.now(); - openingHours: OpeningHours[] = []; - exceptionHours: (ExceptionWorkingHours & { start: string; end: string; description: string })[] = []; + openingHours = signal([]); + exceptionHours = signal<(ExceptionWorkingHours & { start: string; end: string; description: string })[]>([]); + showAllMaintenancePeriods = false; - constructor(private translate: TranslateService, private Calendar: CalendarService) {} + constructor( + private translate: TranslateService, + private Calendar: CalendarService, + ) {} ngOnInit() { this.translate.onLangChange.subscribe(() => { - this.openingHours = this.Calendar.processOpeningHours(this.room); + this.openingHours.set(this.Calendar.processOpeningHours(this.room)); }); } @@ -100,12 +132,17 @@ export class SelectedRoomComponent implements OnInit, OnChanges { getRoomAccessibility = () => this.room.accessibilities ? this.room.accessibilities.map((a) => a.name).join(', ') : ''; + thisWeeksMaintenancePeriods() { + const mp = [...this.maintenancePeriods]; + return mp.filter((p) => { + const start = DateTime.fromISO(p.startsAt); + return start >= this.viewStart && start < this.viewStart.plus({ week: 1 }); + }); + } private init() { - this.openingHours = this.Calendar.processOpeningHours(this.room); - this.exceptionHours = this.Calendar.getExceptionHours( - this.room, - this.viewStart, - this.viewStart.plus({ week: 1 }), + this.openingHours.set(this.Calendar.processOpeningHours(this.room)); + this.exceptionHours.set( + this.Calendar.getExceptionHours(this.room, this.viewStart, this.viewStart.plus({ week: 1 })), ); } } diff --git a/ui/src/app/calendar/helpers/slot-picker.component.html b/ui/src/app/calendar/helpers/slot-picker.component.html index 18dd7fb559..e1c2586f60 100644 --- a/ui/src/app/calendar/helpers/slot-picker.component.html +++ b/ui/src/app/calendar/helpers/slot-picker.component.html @@ -1,74 +1,22 @@ -
+
-

{{ sequenceNumber }}. {{ 'sitnet_calendar_phase_2' | translate }}

+

{{ sequenceNumber }}. {{ 'i18n_calendar_phase_2' | translate }}

- - - - -
-
- -
-
- - - - {{ 'sitnet_calendar_room_accessibility_info' | translate }} - -
-
-
-
- {{ 'sitnet_exam_room_accessibility' | translate }} -
-
-
-
-
- - - {{ accessibility.name }} - -
-
-
+ @if (selectedRoom) { + + -
-
+ } +
-
- -
-
- + + + @if (selectedRoom) { +
+
+ +
-
-
-
- - + } + @if (selectedRoom) { +
+
+ + +
-
+ }
diff --git a/ui/src/app/calendar/helpers/slot-picker.component.ts b/ui/src/app/calendar/helpers/slot-picker.component.ts index 8517c5ae5e..b7c6de7182 100644 --- a/ui/src/app/calendar/helpers/slot-picker.component.ts +++ b/ui/src/app/calendar/helpers/slot-picker.component.ts @@ -1,25 +1,51 @@ +import { NgClass } from '@angular/common'; import { HttpParams } from '@angular/common/http'; import type { SimpleChanges } from '@angular/core'; -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewEncapsulation, signal } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { EventApi, EventInput } from '@fullcalendar/core'; -import { TranslateService } from '@ngx-translate/core'; +import { + NgbCollapse, + NgbDropdown, + NgbDropdownItem, + NgbDropdownMenu, + NgbDropdownToggle, +} from '@ng-bootstrap/ng-bootstrap'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { DateTime } from 'luxon'; import { ToastrService } from 'ngx-toastr'; import type { Observable } from 'rxjs'; -import { MaintenancePeriod } from '../../exam/exam.model'; -import type { Accessibility, ExamRoom } from '../../reservation/reservation.model'; -import type { Organisation, Slot } from '../calendar.service'; -import { CalendarService } from '../calendar.service'; - -type FilterableAccessibility = Accessibility & { filtered: boolean }; +import { BookingCalendarComponent } from 'src/app/calendar/booking-calendar.component'; +import type { Organisation, Slot } from 'src/app/calendar/calendar.service'; +import { CalendarService } from 'src/app/calendar/calendar.service'; +import { MaintenancePeriod } from 'src/app/exam/exam.model'; +import type { Accessibility, ExamRoom } from 'src/app/reservation/reservation.model'; +import { updateList } from 'src/app/shared/miscellaneous/helpers'; +import { AccessibilityPickerComponent } from './accessibility-picker.component'; +import { SelectedRoomComponent } from './selected-room.component'; + +export type FilterableAccessibility = Accessibility & { filtered: boolean }; type FilterableRoom = ExamRoom & { filtered: boolean }; type AvailableSlot = Slot & { availableMachines: number }; @Component({ selector: 'xm-calendar-slot-picker', templateUrl: './slot-picker.component.html', + styleUrls: ['../calendar.component.scss'], encapsulation: ViewEncapsulation.None, + standalone: true, + imports: [ + NgClass, + NgbCollapse, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownItem, + SelectedRoomComponent, + AccessibilityPickerComponent, + BookingCalendarComponent, + TranslateModule, + ], }) export class SlotPickerComponent implements OnInit, OnChanges { @Input() sequenceNumber = 0; @@ -38,13 +64,12 @@ export class SlotPickerComponent implements OnInit, OnChanges { accessibilities: Accessibility[]; }>(); - rooms: FilterableRoom[] = []; - maintenancePeriods: MaintenancePeriod[] = []; + rooms = signal([]); + maintenancePeriods = signal([]); selectedRoom?: ExamRoom; accessibilities: FilterableAccessibility[] = []; - showAccessibilityMenu = false; - currentWeek = DateTime.now(); - examId = 0; + currentWeek = signal(DateTime.now()); + examId = signal(0); constructor( private translate: TranslateService, @@ -54,20 +79,20 @@ export class SlotPickerComponent implements OnInit, OnChanges { ) {} ngOnInit() { - this.examId = Number(this.route.snapshot.paramMap.get('id')); + this.examId.set(Number(this.route.snapshot.paramMap.get('id'))); this.Calendar.listAccessibilityCriteria$().subscribe( (resp) => (this.accessibilities = resp.map((a) => ({ ...a, filtered: false }))), ); this.Calendar.listRooms$().subscribe((resp) => { const rooms = resp.map((r: ExamRoom) => ({ ...r, filtered: false })).filter((r) => r.name); - this.rooms = rooms.sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1)); + this.rooms.set(rooms.sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1))); }); - this.Calendar.listMaintenancePeriods$().subscribe((periods) => (this.maintenancePeriods = periods)); + this.Calendar.listMaintenancePeriods$().subscribe((periods) => this.maintenancePeriods.set(periods)); } ngOnChanges(changes: SimpleChanges) { if (changes.organisation && this.organisation) { - this.rooms = this.organisation.facilities.map((f) => ({ ...f, filtered: false })); + this.rooms.set(this.organisation.facilities.map((f) => ({ ...f, filtered: false }))); delete this.selectedRoom; } } @@ -85,7 +110,7 @@ export class SlotPickerComponent implements OnInit, OnChanges { return; } const start = DateTime.fromISO($event.date, { zone: $event.timeZone }).startOf('week'); - this.currentWeek = start; + this.currentWeek.set(start as DateTime); const accessibilities = this.accessibilities.filter((i) => i.filtered).map((i) => i.id); const getColor = (slot: AvailableSlot) => { @@ -124,33 +149,32 @@ export class SlotPickerComponent implements OnInit, OnChanges { this.cancelled.emit(); }; - selectAccessibility = (accessibility: FilterableAccessibility) => { - accessibility.filtered = !accessibility.filtered; - this.accessibilities = [...this.accessibilities]; // copy to ignite change deteccttion - }; + accesibilitiesChanged = (items: FilterableAccessibility[]) => (this.accessibilities = [...items]); selectRoom = (room: FilterableRoom) => { if (!room.outOfService) { this.selectedRoom = room; - this.rooms.forEach((r) => (r.filtered = false)); - room.filtered = true; + this.rooms.update((rs) => { + const unfiltered = rs.map((r) => ({ ...r, filtered: false })); + return updateList(unfiltered, 'id', { ...room, filtered: true }); + }); } }; getDescription(room: ExamRoom): string { const status = room.statusComment ? ': ' + room.statusComment : ''; - return this.translate.instant('sitnet_room_out_of_service') + status; + return this.translate.instant('i18n_room_out_of_service') + status; } outOfServiceGate = (room: ExamRoom, text: string) => (room.outOfService ? text : undefined); private getTitle(slot: AvailableSlot): string { if (slot.availableMachines > 0) { - return `${this.translate.instant('sitnet_slot_available')} (${slot.availableMachines})`; + return `${this.translate.instant('i18n_slot_available')} (${slot.availableMachines})`; } else { return slot.conflictingExam - ? this.translate.instant('sitnet_own_reservation') - : this.translate.instant('sitnet_reserved'); + ? this.translate.instant('i18n_own_reservation') + : this.translate.instant('i18n_reserved'); } } @@ -162,7 +186,7 @@ export class SlotPickerComponent implements OnInit, OnChanges { ? { org: this.organisation._id, date: date } : { day: date, aids: accessibilityIds.map((i) => i.toString()) }, }); - return this.Calendar.listSlots$(this.isExternal, this.isCollaborative, room, this.examId, params); + return this.Calendar.listSlots$(this.isExternal, this.isCollaborative, room, this.examId(), params); } private adjust = (date: string, tz: string): Date => { diff --git a/ui/src/app/dashboard/staff/admin/admin-dashboard.component.ts b/ui/src/app/dashboard/staff/admin/admin-dashboard.component.ts index c67acc31c5..d1cba455fa 100644 --- a/ui/src/app/dashboard/staff/admin/admin-dashboard.component.ts +++ b/ui/src/app/dashboard/staff/admin/admin-dashboard.component.ts @@ -13,9 +13,12 @@ * See the Licence for the specific language governing permissions and limitations under the Licence. */ import { Component } from '@angular/core'; +import { ReservationsComponent } from 'src/app/reservation/reservations.component'; @Component({ selector: 'xm-admin-dashboard', template: '', + standalone: true, + imports: [ReservationsComponent], }) export class AdminDashboardComponent {} diff --git a/ui/src/app/dashboard/staff/staff-dashboard.component.ts b/ui/src/app/dashboard/staff/staff-dashboard.component.ts index 24156bdfcf..26c861fdf9 100644 --- a/ui/src/app/dashboard/staff/staff-dashboard.component.ts +++ b/ui/src/app/dashboard/staff/staff-dashboard.component.ts @@ -13,9 +13,12 @@ * See the Licence for the specific language governing permissions and limitations under the Licence. */ import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; @Component({ selector: 'xm-staff-dashboard', template: ``, + standalone: true, + imports: [RouterOutlet], }) export class StaffDashboardComponent {} diff --git a/ui/src/app/dashboard/staff/staff-dashboard.module.ts b/ui/src/app/dashboard/staff/staff-dashboard.module.ts deleted file mode 100644 index e06d0176ef..0000000000 --- a/ui/src/app/dashboard/staff/staff-dashboard.module.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2018 Exam Consortium - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent - * versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * - * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed - * on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and limitations under the Licence. - */ -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { AdministrativeModule } from '../../administrative/administrative.module'; -import { ExamModule } from '../../exam/exam.module'; -import { ExaminationModule } from '../../examination/examination.module'; -import { FacilityModule } from '../../facility/facility.module'; -import { MaturityModule } from '../../maturity/maturity.module'; -import { QuestionModule } from '../../question/question.module'; -import { ReviewModule } from '../../review/review.module'; -import { SharedModule } from '../../shared/shared.module'; -import { SoftwareModule } from '../../software/software.module'; -import { AdminDashboardModule } from './admin/admin-dashboard.module'; -import { StaffDashboardComponent } from './staff-dashboard.component'; -import { StaffRoutingModule } from './staff-routing.module'; -import { TeacherDashboardModule } from './teacher/teacher-dashboard.module'; - -// TODO: Student & teacher dashboard + reservation modules should be lazy loaded to decrease bundle size -// We need a router setup that supports this first -@NgModule({ - imports: [ - SharedModule, - TeacherDashboardModule, - AdminDashboardModule, - ExamModule, - ExaminationModule, - QuestionModule, - ReviewModule, - MaturityModule, - AdministrativeModule, - SoftwareModule, - FacilityModule, - RouterModule, - StaffRoutingModule, - ], - declarations: [StaffDashboardComponent], -}) -export class StaffDashboardModule {} diff --git a/ui/src/app/dashboard/staff/staff-routing.module.ts b/ui/src/app/dashboard/staff/staff.routes.ts similarity index 56% rename from ui/src/app/dashboard/staff/staff-routing.module.ts rename to ui/src/app/dashboard/staff/staff.routes.ts index dc71f869cf..285b06eda3 100644 --- a/ui/src/app/dashboard/staff/staff-routing.module.ts +++ b/ui/src/app/dashboard/staff/staff.routes.ts @@ -1,47 +1,54 @@ -import { NgModule } from '@angular/core'; -import { Route, RouterModule } from '@angular/router'; +import { inject } from '@angular/core'; +import { ActivatedRouteSnapshot, Route } from '@angular/router'; +import { ReportsComponent } from 'src/app/administrative/reports/reports.component'; +import { SettingsComponent } from 'src/app/administrative/settings/settings.component'; +import { StatisticsComponent } from 'src/app/administrative/statistics/statistics.component'; +import { UsersComponent } from 'src/app/administrative/users/users.component'; +import { CollaborativeExamListingComponent } from 'src/app/exam/collaborative/collaborative-exam-listing.component'; +import { CollaborativeExamService } from 'src/app/exam/collaborative/collaborative-exam.service'; import { ExamAssessmentComponent } from 'src/app/exam/editor/assessment/exam-assessment.component'; import { BasicExamInfoComponent } from 'src/app/exam/editor/basic/basic-exam-info.component'; -import { ExamResolverService } from 'src/app/exam/editor/basic/exam-resolver.service'; +import { CourseSelectionComponent } from 'src/app/exam/editor/creation/course-selection.component'; +import { NewExamComponent } from 'src/app/exam/editor/creation/new-exam.component'; +import { ExaminationEventSearchComponent } from 'src/app/exam/editor/events/examination-event-search.component'; import { ExamTabsComponent } from 'src/app/exam/editor/exam-tabs.component'; +import { ExamTabService } from 'src/app/exam/editor/exam-tabs.service'; import { ExamPublicationComponent } from 'src/app/exam/editor/publication/exam-publication.component'; import { SectionsComponent } from 'src/app/exam/editor/sections/sections.component'; +import { ExamService } from 'src/app/exam/exam.service'; +import { ExamListingComponent } from 'src/app/exam/listing/exam-list.component'; import { PrintoutComponent } from 'src/app/exam/printout/printout.component'; -import { QuestionEditQuard } from 'src/app/question/question-edit-guard'; -import { ReviewListResolverService } from 'src/app/review/listing/review-list-resolver.service'; +import { PrintoutListingComponent } from 'src/app/exam/printout/printouts.component'; +import { ExaminationComponent } from 'src/app/examination/examination.component'; +import { FacilityComponent } from 'src/app/facility/facility.component'; +import { MachineComponent } from 'src/app/facility/machines/machine.component'; +import { AvailabilityComponent } from 'src/app/facility/rooms/availability.component'; +import { MultiRoomComponent } from 'src/app/facility/rooms/room-mass-edit.component'; +import { RoomComponent } from 'src/app/facility/rooms/room.component'; +import { LanguageInspectionsComponent } from 'src/app/maturity/language-inspections.component'; +import { MaturityReportingComponent } from 'src/app/maturity/reporting/maturity-reporting.component'; +import { QuestionComponent } from 'src/app/question/basequestion/question.component'; +import { hasUnsavedChangesGuard } from 'src/app/question/has-unsaved-changes.quard'; +import { LibraryComponent } from 'src/app/question/library/library.component'; +import { ReservationsComponent } from 'src/app/reservation/reservations.component'; +import { AssessmentComponent } from 'src/app/review/assessment/assessment.component'; +import { PrintedAssessmentComponent } from 'src/app/review/assessment/print/printed-assessment.component'; import { ReviewListComponent } from 'src/app/review/listing/review-list.component'; -import { ExamSummaryComponent } from 'src/app/review/listing/summary/exam-summary.component'; +import { ReviewListService } from 'src/app/review/listing/review-list.service'; +import { SpeedReviewComponent } from 'src/app/review/listing/speed-review.component'; +import { QuestionAssessmentComponent } from 'src/app/review/questions/assessment/question-assessment.component'; import { QuestionReviewsComponent } from 'src/app/review/questions/listing/question-reviews.component'; -import { ReportsComponent } from '../../administrative/reports/reports.component'; -import { SettingsComponent } from '../../administrative/settings/settings.component'; -import { StatisticsComponent } from '../../administrative/statistics/statistics.component'; -import { UsersComponent } from '../../administrative/users/users.component'; -import { CollaborativeExamListingComponent } from '../../exam/collaborative/collaborative-exam-listing.component'; -import { CourseSelectionComponent } from '../../exam/editor/creation/course-selection.component'; -import { NewExamComponent } from '../../exam/editor/creation/new-exam.component'; -import { ExaminationEventSearchComponent } from '../../exam/editor/events/examination-event-search.component'; -import { ExamListingComponent } from '../../exam/listing/exam-list.component'; -import { PrintoutListingComponent } from '../../exam/printout/printouts.component'; -import { ExaminationComponent } from '../../examination/examination.component'; -import { FacilityComponent } from '../../facility/facility.component'; -import { MachineComponent } from '../../facility/machines/machine.component'; -import { AvailabilityComponent } from '../../facility/rooms/availability.component'; -import { MultiRoomComponent } from '../../facility/rooms/room-mass-edit.component'; -import { RoomComponent } from '../../facility/rooms/room.component'; -import { LanguageInspectionsComponent } from '../../maturity/language-inspections.component'; -import { MaturityReportingComponent } from '../../maturity/reporting/maturity-reporting.component'; -import { QuestionComponent } from '../../question/basequestion/question.component'; -import { LibraryComponent } from '../../question/library/library.component'; -import { ReservationsComponent } from '../../reservation/reservations.component'; -import { AssessmentComponent } from '../../review/assessment/assessment.component'; -import { PrintedAssessmentComponent } from '../../review/assessment/print/printed-assessment.component'; -import { SpeedReviewComponent } from '../../review/listing/speed-review.component'; -import { QuestionAssessmentComponent } from '../../review/questions/assessment/question-assessment.component'; import { AdminDashboardComponent } from './admin/admin-dashboard.component'; import { StaffDashboardComponent } from './staff-dashboard.component'; import { TeacherDashboardComponent } from './teacher/teacher-dashboard.component'; -const routes: Route[] = [ +const reviewListResolver = (route: ActivatedRouteSnapshot) => { + const id = route.pathFromRoot[3].params.id; // hacky yes + const isCollab = inject(ExamTabService).isCollaborative() || route.queryParamMap.get('collaborative') === 'true'; + return inject(ReviewListService).getReviews$(id, isCollab); +}; + +export const STAFF_ROUTES: Route[] = [ { path: '', component: StaffDashboardComponent, @@ -57,20 +64,28 @@ const routes: Route[] = [ newQuestion: false, nextState: 'questions', }, - canDeactivate: [QuestionEditQuard], + canDeactivate: [hasUnsavedChangesGuard], }, { path: 'questions/new', component: QuestionComponent, data: { newQuestion: true }, - canDeactivate: [QuestionEditQuard], + canDeactivate: [hasUnsavedChangesGuard], }, { path: 'exams', component: NewExamComponent }, { path: 'exams/:id', component: ExamTabsComponent, - resolve: { exam: ExamResolverService }, + resolve: { + exam: (route: ActivatedRouteSnapshot) => { + const id = Number(route.paramMap.get('id')); + const isCollab = route.queryParamMap.get('collaborative') === 'true'; + return isCollab + ? inject(CollaborativeExamService).download$(id) + : inject(ExamService).downloadExam$(id); + }, + }, children: [ { path: '1', component: BasicExamInfoComponent }, { path: '2', component: SectionsComponent }, @@ -79,13 +94,16 @@ const routes: Route[] = [ { path: '5', component: ReviewListComponent, - resolve: { reviews: ReviewListResolverService }, + resolve: { reviews: reviewListResolver }, }, { path: '6', component: QuestionReviewsComponent }, { path: '7', - component: ExamSummaryComponent, - resolve: { reviews: ReviewListResolverService }, + loadComponent: () => + import('../../review/listing/summary/exam-summary.component').then( + (mod) => mod.ExamSummaryComponent, + ), + resolve: { reviews: reviewListResolver }, }, ], }, @@ -150,9 +168,3 @@ const routes: Route[] = [ ], }, ]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class StaffRoutingModule {} diff --git a/ui/src/app/dashboard/staff/teacher/categories/exam-list-category.component.html b/ui/src/app/dashboard/staff/teacher/categories/exam-list-category.component.html index 88173304ad..ee526cd87c 100644 --- a/ui/src/app/dashboard/staff/teacher/categories/exam-list-category.component.html +++ b/ui/src/app/dashboard/staff/teacher/categories/exam-list-category.component.html @@ -1,11 +1,11 @@ -
-
-