diff --git a/.jhipster/Choice.json b/.jhipster/Choice.json new file mode 100644 index 0000000..f5318d2 --- /dev/null +++ b/.jhipster/Choice.json @@ -0,0 +1,46 @@ +{ + "annotations": { + "changelogDate": "20261020093324" + }, + "applications": ["*"], + "dto": "mapstruct", + "fields": [ + { + "fieldName": "optionKey", + "fieldType": "OptionKey", + "fieldValidateRules": ["required"], + "fieldValues": "A,B,C,D" + }, + { + "fieldName": "content", + "fieldType": "String", + "fieldValidateRules": ["required", "maxlength"], + "fieldValidateRulesMaxlength": "500" + }, + { + "fieldName": "displayOrder", + "fieldType": "Integer", + "fieldValidateRules": ["required", "min", "max"], + "fieldValidateRulesMax": "4", + "fieldValidateRulesMin": "1" + }, + { + "fieldName": "correct", + "fieldType": "Boolean", + "fieldValidateRules": ["required"] + } + ], + "name": "Choice", + "relationships": [ + { + "otherEntityName": "question", + "otherEntityRelationshipName": "choice", + "relationshipName": "question", + "relationshipSide": "right", + "relationshipType": "many-to-one", + "relationshipValidateRules": "required" + } + ], + "searchEngine": "no", + "service": "serviceClass" +} diff --git a/.jhipster/ExamAnswer.json b/.jhipster/ExamAnswer.json new file mode 100644 index 0000000..d4cfbdf --- /dev/null +++ b/.jhipster/ExamAnswer.json @@ -0,0 +1,62 @@ +{ + "annotations": { + "changelogDate": "20261020093326" + }, + "applications": ["*"], + "dto": "mapstruct", + "fields": [ + { + "fieldName": "questionTextSnapshot", + "fieldType": "String", + "fieldValidateRules": ["required", "maxlength"], + "fieldValidateRulesMaxlength": "2000" + }, + { + "fieldName": "explanationSnapshot", + "fieldType": "String", + "fieldValidateRules": ["maxlength"], + "fieldValidateRulesMaxlength": "2000" + }, + { + "fieldName": "selectedOption", + "fieldType": "OptionKey", + "fieldValues": "A,B,C,D" + }, + { + "fieldName": "selectedContentSnapshot", + "fieldType": "String", + "fieldValidateRules": ["maxlength"], + "fieldValidateRulesMaxlength": "500" + }, + { + "fieldName": "correct", + "fieldType": "Boolean" + }, + { + "fieldName": "awardedPoints", + "fieldType": "Integer", + "fieldValidateRules": ["min"], + "fieldValidateRulesMin": "0" + } + ], + "name": "ExamAnswer", + "relationships": [ + { + "otherEntityName": "question", + "relationshipName": "question", + "relationshipSide": "left", + "relationshipType": "many-to-one", + "relationshipValidateRules": "required" + }, + { + "otherEntityName": "examAttempt", + "otherEntityRelationshipName": "answer", + "relationshipName": "attempt", + "relationshipSide": "right", + "relationshipType": "many-to-one", + "relationshipValidateRules": "required" + } + ], + "searchEngine": "no", + "service": "serviceClass" +} diff --git a/.jhipster/ExamAttempt.json b/.jhipster/ExamAttempt.json new file mode 100644 index 0000000..0340096 --- /dev/null +++ b/.jhipster/ExamAttempt.json @@ -0,0 +1,60 @@ +{ + "annotations": { + "changelogDate": "20261020093325" + }, + "applications": ["*"], + "dto": "mapstruct", + "fields": [ + { + "fieldName": "startedAt", + "fieldType": "Instant", + "fieldValidateRules": ["required"] + }, + { + "fieldName": "submittedAt", + "fieldType": "Instant" + }, + { + "fieldName": "status", + "fieldType": "AttemptStatus", + "fieldValidateRules": ["required"], + "fieldValues": "IN_PROGRESS,SUBMITTED" + }, + { + "fieldName": "score", + "fieldType": "Integer", + "fieldValidateRules": ["min"], + "fieldValidateRulesMin": "0" + } + ], + "name": "ExamAttempt", + "pagination": "pagination", + "relationships": [ + { + "otherEntityName": "examAnswer", + "otherEntityRelationshipName": "attempt", + "relationshipName": "answer", + "relationshipSide": "left", + "relationshipType": "one-to-many" + }, + { + "otherEntityField": "name", + "otherEntityName": "subject", + "relationshipName": "subject", + "relationshipSide": "left", + "relationshipType": "many-to-one", + "relationshipValidateRules": "required" + }, + { + "otherEntityField": "login", + "otherEntityName": "user", + "relationshipName": "user", + "relationshipSide": "left", + "relationshipType": "many-to-one", + "relationshipValidateRules": "required", + "relationshipWithBuiltInEntity": true + } + ], + "searchEngine": "no", + "service": "serviceClass" +} diff --git a/.jhipster/Question.json b/.jhipster/Question.json new file mode 100644 index 0000000..5c82c3a --- /dev/null +++ b/.jhipster/Question.json @@ -0,0 +1,48 @@ +{ + "annotations": { + "changelogDate": "20261020093323" + }, + "applications": ["*"], + "dto": "mapstruct", + "fields": [ + { + "fieldName": "prompt", + "fieldType": "String", + "fieldValidateRules": ["required", "minlength", "maxlength"], + "fieldValidateRulesMaxlength": "2000", + "fieldValidateRulesMinlength": "5" + }, + { + "fieldName": "explanation", + "fieldType": "String", + "fieldValidateRules": ["maxlength"], + "fieldValidateRulesMaxlength": "2000" + }, + { + "fieldName": "active", + "fieldType": "Boolean", + "fieldValidateRules": ["required"] + } + ], + "name": "Question", + "pagination": "pagination", + "relationships": [ + { + "otherEntityName": "choice", + "otherEntityRelationshipName": "question", + "relationshipName": "choice", + "relationshipSide": "left", + "relationshipType": "one-to-many" + }, + { + "otherEntityField": "name", + "otherEntityName": "subject", + "relationshipName": "subject", + "relationshipSide": "left", + "relationshipType": "many-to-one", + "relationshipValidateRules": "required" + } + ], + "searchEngine": "no", + "service": "serviceClass" +} diff --git a/.jhipster/Subject.json b/.jhipster/Subject.json new file mode 100644 index 0000000..3ba1203 --- /dev/null +++ b/.jhipster/Subject.json @@ -0,0 +1,32 @@ +{ + "annotations": { + "changelogDate": "20261020093322" + }, + "applications": ["*"], + "dto": "mapstruct", + "fields": [ + { + "fieldName": "name", + "fieldType": "String", + "fieldValidateRules": ["required", "minlength", "maxlength"], + "fieldValidateRulesMaxlength": "100", + "fieldValidateRulesMinlength": "2" + }, + { + "fieldName": "description", + "fieldType": "String", + "fieldValidateRules": ["maxlength"], + "fieldValidateRulesMaxlength": "1000" + }, + { + "fieldName": "active", + "fieldType": "Boolean", + "fieldValidateRules": ["required"] + } + ], + "name": "Subject", + "pagination": "pagination", + "relationships": [], + "searchEngine": "no", + "service": "serviceClass" +} diff --git a/.yo-rc.json b/.yo-rc.json index 1589107..7badaf7 100644 --- a/.yo-rc.json +++ b/.yo-rc.json @@ -11,10 +11,11 @@ "databaseType": "sql", "defaultCommand": "app", "devDatabaseType": "postgresql", - "entities": [], + "entities": ["Subject", "Question", "Choice", "ExamAttempt", "ExamAnswer"], "jhipsterVersion": "9.3.0", "jwtSecretKey": "MzY1ZDU0MDM3M2Y5YWRiMDYxYjBmYzZlOTMxMWFiNmYyMDEyZTUzZjYxOWFjNjhlNjU2NzcxYjkwY2Y0MGIwOGUyNTc5NWQyOGY3OGJkMjExZjhkYzU3ZGU4ZDc0ZmZiMTYwMzY0NGM4ZWZmODRhZTZjNzBlNjk5MWJkYjM5YjI=", "languages": ["en"], + "lastLiquibaseTimestamp": 1792488806000, "messageBroker": "no", "nativeLanguage": "en", "packageName": "com.example.questionbank", diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..999af70 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12613 @@ +{ + "name": "question-bank", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "question-bank", + "version": "0.0.0", + "license": "UNLICENSED", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "7.3.1", + "@fortawesome/free-solid-svg-icons": "7.3.1", + "@fortawesome/vue-fontawesome": "3.3.3", + "@vuelidate/core": "2.0.3", + "@vuelidate/validators": "2.0.4", + "@vueuse/core": "14.4.0", + "axios": "1.19.0", + "bootstrap": "5.3.7", + "bootstrap-vue-next": "1.0.1", + "dayjs": "1.11.23", + "deepmerge": "4.3.1", + "pinia": "4.0.3", + "vue": "3.5.41", + "vue-i18n": "11.4.9", + "vue-router": "5.2.0" + }, + "devDependencies": { + "@eslint/js": "10.0.1", + "@pinia/testing": "2.0.1", + "@tsconfig/node18": "18.2.7", + "@types/node": "22.20.1", + "@vitejs/plugin-vue": "6.0.8", + "@vitest/coverage-v8": "4.1.11", + "@vue/test-utils": "2.4.11", + "@vue/tsconfig": "0.9.1", + "autoprefixer": "10.5.4", + "axios-mock-adapter": "2.1.0", + "concurrently": "10.0.5", + "eslint": "10.9.1", + "eslint-config-prettier": "10.1.8", + "eslint-plugin-prettier": "5.5.6", + "eslint-plugin-vue": "10.10.0", + "generator-jhipster": "9.3.0", + "globals": "17.11.0", + "happy-dom": "20.11.6", + "husky": "9.1.7", + "jiti": "2.7.0", + "lint-staged": "17.3.0", + "postcss-import": "17.0.0", + "postcss-url": "10.1.4", + "prettier": "3.9.6", + "prettier-plugin-java": "2.10.3", + "prettier-plugin-packagejson": "3.0.2", + "rimraf": "6.1.3", + "sass": "1.70.0", + "swagger-ui-dist": "5.32.14", + "typescript": "6.0.3", + "typescript-eslint": "8.68.0", + "vite": "8.2.2", + "vite-plugin-static-copy": "4.1.1", + "vitest": "4.1.11", + "vitest-sonar-reporter": "3.0.0", + "wait-on": "9.1.0" + }, + "engines": { + "node": ">=24.20.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.6.tgz", + "integrity": "sha512-/pcanjdRsonCexCuxgGD8fKnBLLzk2i9uM4kmcmGyyev2R5YDs+rafMYZ89RvaGY1mW8T7C5au0TyYaEeHBGng==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^8.0.6", + "@babel/types": "^8.0.6", + "@jridgewell/gen-mapping": "0.4.0-beta.0", + "@jridgewell/trace-mapping": "^0.3.31", + "@types/jsesc": "^2.5.0", + "jsesc": "^3.0.2" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/helper-string-parser": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.6.tgz", + "integrity": "sha512-+6HYEBnsDRZHJtUTAEfMQd0zMDqdFHS7C+5vAsEZqBUr3vEMWOWlHJ0Jz1gS8jJIlCvLsuA6ivmeoqzH936YcA==", + "license": "MIT", + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/helper-validator-identifier": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.6.tgz", + "integrity": "sha512-HYx0YmuchRxRSpnjvcNffnPS8DCauKNmnumIuHG3jnQAVewRA7kfJGwF13ayEpSZs7s4R/oBH4eppuXcAQd5JQ==", + "license": "MIT", + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/parser": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.7.tgz", + "integrity": "sha512-UkDwEbPO1px2JQSrdh4qIgaH1JgG7GO/pFeJkpxhDxIETkT/QvGpnigXIw75ViHYPtIgKITmVUJqLjiO+JuWjA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^8.0.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/types": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.6.tgz", + "integrity": "sha512-c+xgSWboV2pdwXP67BUWDVRHi2BO5Q3KwxyFVs7taVTY+fsK47/L51ZXQoV9rozHJDNHvJ4v4WEsI/IlxV2l2A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^8.0.6", + "@babel/helper-validator-identifier": "^8.0.6" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-13.2.0.tgz", + "integrity": "sha512-bA9dvWlhAUcHkNwU+8w9yiUxJPlj/Lm3VqS7MD+NbIR/7LmpNLuK/AWNFdCo/T3SK5ND0/UHf3IJvl/Jn/i6yg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "13.2.0", + "@chevrotain/types": "13.2.0" + } + }, + "node_modules/@chevrotain/gast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-13.2.0.tgz", + "integrity": "sha512-bCARdAsG+eEbOveSXcOAC7pVxA04I1ionzeMOwIYf5NX7SaS7zgn4Dgug2BSqoL+iyKeMNSorQjsFSHJHsCNwg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "13.2.0" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-13.2.0.tgz", + "integrity": "sha512-kxpUkLtiaK09ph+dib+Yvm+3sWSnuwlo25gqfKRgTPNmF6H7uW4gVkMjaRdtnN783S9sM6vUNWh9CsxYX4QwKw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-13.2.0.tgz", + "integrity": "sha512-7qrYHRlKfWf2AvBfJi5eVOrKAkbxvMFsy/iIHTGIiApNcEecCaVIdR+mIQhyCBsTDJxBz4JWXHMo6krbhR9hVg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-13.2.0.tgz", + "integrity": "sha512-SzKYY68rseOrb9KILVzPsl6SjkQtdWw01SRGB5aCVI5kFcHltQsOYV3JB0Ffst72DgkvHCyDQ0NLwxtmCCf97Q==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", + "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@faker-js/faker": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.6.0.tgz", + "integrity": "sha512-3RQHgEtvL1Frl/d1cSreo7qhJ3Gk1OdNUai/CtZ8G+wYeRQnJih3s9xJ9/kgYekPQRdwgh0HXRPqMlzWGwivIQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0", + "npm": ">=10" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "license": "MIT" + }, + "node_modules/@floating-ui/vue": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@floating-ui/vue/-/vue-2.0.1.tgz", + "integrity": "sha512-043dyEKD9TDSfz080YH2vobubgg+NIo/9Fw4RAl7sEMpD8Am1DNrrSTl/GpMBjyGHoD/FbJY2QLawY+HSQsEIA==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + }, + "peerDependencies": { + "vue": ">=3.3.0" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.3.1.tgz", + "integrity": "sha512-k0C0sdHmZtAo6dRDtd1Z/qcpyHbL0CKsjV8seMY/21xGhY5Wsv0XRmiI/xEEH4y2c9b1+jvgNs/3EqhV27yUEA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.3.1.tgz", + "integrity": "sha512-BoxVN3PKnMbgStHhjoaky/oWdxHomDqmBVA24IA3KEmssFGeI7u9YT/BJceOjIum/t6TpPa/vcMKaVYQeIQ/3Q==", + "license": "MIT", + "dependencies": { + "@fortawesome/fontawesome-common-types": "7.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.3.1.tgz", + "integrity": "sha512-v0BLa0eqg7ubvVWeNSHVBs8fWH/GJicERZoJaxJ3FE/lj67VSqzoMg9pzfZVOfLMX10y0pGwQAuxoRVVH2patg==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "7.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/vue-fontawesome": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.3.3.tgz", + "integrity": "sha512-Jbjze98gGcVBSdkscLbnDlHECumMAFVWDarMtycctn9qL3p92ApnV36VW4PwVrcm9IWrHnnE6ZL9x7MXStSCfA==", + "license": "MIT", + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7", + "vue": ">= 3.0.0 < 4" + } + }, + "node_modules/@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@hapi/address": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", + "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/formula": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", + "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/hoek": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", + "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/pinpoint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", + "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/tlds": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.1.7.tgz", + "integrity": "sha512-MgNjRwy9Ti92yVAixLmDc8dd1bJIKwO9qlWCfFQRwRmUEDPQHYn4G6hwPFvFGUTzAa0FsS+inMjLin7GnyBRhA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hapi/topo": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", + "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@iarna/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/@inquirer/ansi": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.9.tgz", + "integrity": "sha512-0Ywt3S8tqM6TWUcsRlBFQ1x+X3/o8kktX0ZiKAnByYb9GFDknnOhse1PVtfiD2BXPI8ar+BWx9PV9R0lQIcygw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.7.tgz", + "integrity": "sha512-/+QmGE/9bvE/EobaZDnzYe+T+QWoJrnmxwBQNtoi2OVSUR9d1znYsNyEoUrOZvFSxDYttrhzRIpXpaLkN+iIsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/core": "^12.0.5", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/checkbox/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.3.4.tgz", + "integrity": "sha512-ZwnaZZDa1zxsyVrN32s447ydMnKcw7e8WWNT+R+Qsu0zAn8Rs6yi9d1B80Kob1Ul2cfUi7t8JD2t4/K7uEZpqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.2.1.tgz", + "integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.7", + "@inquirer/figures": "^2.0.7", + "@inquirer/type": "^4.0.7", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.3.5.tgz", + "integrity": "sha512-6lU3/pPx5z3lHWejFW061MV4qZooBQYv/+EeGhNOPiP/i+hrYsHfxxBnnDGsAfg8YdLUd69YckoeOjtr3QuAUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/external-editor": "^3.0.6", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.7.tgz", + "integrity": "sha512-eiJ31YFCaB6fLoJCqLIn8S6eqUyME6vwr8KcP5h8cxmA+bV9RRVPO+kywoxb7G63HduDXV6sN/SM7o2R+ahEcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.6.tgz", + "integrity": "sha512-rWmw6WG8JZ7LMn/srXEylYGhL6EXXJeROE7/4x4GREh6NgzqJBDbIgpNGsYoLPfobeb4VZtEYzPGnT5EFNYhiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.2" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.9.tgz", + "integrity": "sha512-EAWgUTGQ/Umgga51dE3B2PUHbufuXarDfg86uVgoSgNHNNQnyFKcOrQLWVqYMghuSyHh8+2HUH0Js9cTC1WAdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + } + }, + "node_modules/@inquirer/input": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.8.tgz", + "integrity": "sha512-psOSTgkL8y/OtgJJYbqJ0oISr2QBE0U1Ro/qQdA/EKjeJiwiUTQgQmq8o4ESNzVOWthIeh3YLD7BCUR9dKnR5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/input/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.2.5.tgz", + "integrity": "sha512-lEy7LWsdF5qHx5QjHZqabUqM9P7i5uTMCt8GRzqxmwXXKbapKJDA+ucVflVVPAyj4snD5DTAD4L+sct85XOlOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.2.4.tgz", + "integrity": "sha512-T7ir3fflSSVCYEVqNyMBq+pIMsilQRtbZcD5gxn6Ewsin5TJWBxrGBdXveWtmeXVAeoInfhS+BhBUZaL4sFSDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/core": "^12.0.5", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "8.7.4", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.7.4.tgz", + "integrity": "sha512-SAJt+QhY5rOJAIgZBw9TrHWfgrp6wsb9cqRCyqax+Hl6EiFfRXmD9EsIWkST8yq/dQ8H46Is2Sr/JG7Ls/LQ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^5.2.7", + "@inquirer/confirm": "^6.3.4", + "@inquirer/editor": "^5.3.5", + "@inquirer/expand": "^5.1.7", + "@inquirer/input": "^5.1.8", + "@inquirer/number": "^4.2.5", + "@inquirer/password": "^5.2.4", + "@inquirer/rawlist": "^5.3.7", + "@inquirer/search": "^4.3.5", + "@inquirer/select": "^5.2.7" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.7.tgz", + "integrity": "sha512-XveEe8v3BHj9ec00n+9i8FHjWhXjS6+jCTizYvXCqKUKtgkrq9xid8S5j3mYGW96qfxG3mwNoud3m3v8GDk9Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.3.5.tgz", + "integrity": "sha512-kIUecMugEN2YTvTmff+uYz0nAE0f9RFNDVZknfrh264vAQM9P8tnsXiUp7z8XbGuNIBEtFMJhvc9QquawpC46A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^12.0.5", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.7.tgz", + "integrity": "sha512-pRDWO4dTqSAvFQdO8yclKMtXNDm9K9HmvWB5UZmT3clw2OlOBNXveHzhyFmO/0d0yJMqlPcNITus1Jtpm6t8VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/core": "^12.0.5", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select/node_modules/@inquirer/core": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.5.tgz", + "integrity": "sha512-c0ZSnO9oVk/IlEGoZK3u8b3IZQeu9I6jUkXJSQnQEVRXsjKvtAq3AGqFL2LgfJhlzMZne08pZHWRWasIcI3Rew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.9", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.2.0", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.2.0.tgz", + "integrity": "sha512-2rnHX8RPo4glJYqnFc/v3nQeIhDcjyRRyaT7MGcfL/8xv/8K03SXYoA2tX06WVSKywWOE/ncbG3dtuzLjR5TCQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@internationalized/date": { + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.4.tgz", + "integrity": "sha512-M1dEn4c1U1HsSlaVR8upZtSqvXrTkHDfv18H01uCSJyjVLDxnBR38v/fMxecmlwXKR4i9HeZcmgQAPE6A+aGJQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.9.tgz", + "integrity": "sha512-GgWy2caO/+hV9sT/oCTWGHvbjmJMPT9kkXzoKRLnkEq7adghhR7UprhvY9sXrKfrp3NcDfhF6QQHXR1KfQbB8g==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@intlify/core-base": { + "version": "11.4.9", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.4.9.tgz", + "integrity": "sha512-qbGZHXBUwodVCxm6E/IXY0yVLGHuh0GDxnoeCZ5FB75Wq5koKHLrANw5cFhC8fT3WyrkDyvesRzMoFOWsLpPOw==", + "license": "MIT", + "dependencies": { + "@intlify/devtools-types": "11.4.9", + "@intlify/message-compiler": "11.4.9", + "@intlify/shared": "11.4.9" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/devtools-types": { + "version": "11.4.9", + "resolved": "https://registry.npmjs.org/@intlify/devtools-types/-/devtools-types-11.4.9.tgz", + "integrity": "sha512-DFwTGShMQBK9ODzt+EKTRdoHdD65fTA/KbgxBq5gSEsbwYZKVFUKfHwnOYvZnZDL+h56swwXcP6jYRmQMOomvg==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.4.9", + "@intlify/shared": "11.4.9" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.4.9", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.4.9.tgz", + "integrity": "sha512-4vlAQsttSX1NgyDOY3sXAEq7HiQPvy21YgBeQUc7Ylu66MwLYVvtqOYSYudDR/SyOahttXvezuNs52s+G104xA==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "11.4.9", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.4.9", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.4.9.tgz", + "integrity": "sha512-4qMBu3D64EN5KbkAj9Mv3TFjiPHtKG/YNd5LU5bpb0DZMR+bKh9/uGNx2GovzxWn2Wnyh5uvEhbPR718EVSkCw==", + "license": "MIT", + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "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/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.4.0-beta.0", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.4.0-beta.0.tgz", + "integrity": "sha512-JdGNkbE4GlNPYQhM0L95fBQr7ctLZJ276QXQLTad4t1oSdnnCI3fDq9DW3BqYAWv8Wc3+HS+4Gsii1oPMCfz1w==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.6.0-beta.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@napi-rs/nice": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", + "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.1.1", + "@napi-rs/nice-android-arm64": "1.1.1", + "@napi-rs/nice-darwin-arm64": "1.1.1", + "@napi-rs/nice-darwin-x64": "1.1.1", + "@napi-rs/nice-freebsd-x64": "1.1.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", + "@napi-rs/nice-linux-arm64-gnu": "1.1.1", + "@napi-rs/nice-linux-arm64-musl": "1.1.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", + "@napi-rs/nice-linux-s390x-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-musl": "1.1.1", + "@napi-rs/nice-openharmony-arm64": "1.1.1", + "@napi-rs/nice-win32-arm64-msvc": "1.1.1", + "@napi-rs/nice-win32-ia32-msvc": "1.1.1", + "@napi-rs/nice-win32-x64-msvc": "1.1.1" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", + "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", + "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", + "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", + "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", + "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", + "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", + "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", + "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", + "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", + "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", + "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", + "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", + "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-openharmony-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", + "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", + "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", + "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", + "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz", + "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@nodable/entities": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.1.0.tgz", + "integrity": "sha512-LsS/DjHr+uDM647Gru/cA8+J3a3HfhttwCKLyuoyN7yXTFCxKBtSgMQBvrW9yNPa2/zDRUNuGPaH5QUFoa4arQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.2.tgz", + "integrity": "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==", + "dev": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^11.2.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/arborist": { + "version": "9.9.3", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.9.3.tgz", + "integrity": "sha512-OxRSMNRPzL2/x2zsVrzdMZItfNj3cVXZIYgGNlUaBRUyH16YKdwN1r9z+I13keR1mjVNKelMfi2a7A/0JJ4NCw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^5.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/metavuln-calculator": "^9.0.2", + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/query": "^5.0.0", + "@npmcli/redact": "^4.0.0", + "@npmcli/run-script": "^10.0.0", + "bin-links": "^6.0.0", + "cacache": "^20.0.1", + "common-ancestor-path": "^2.0.0", + "hosted-git-info": "^9.0.0", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^11.2.1", + "minimatch": "^10.0.3", + "nopt": "^9.0.0", + "npm-install-checks": "^8.0.0", + "npm-package-arg": "^13.0.0", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "pacote": "^21.0.2", + "parse-conflict-json": "^5.0.1", + "proc-log": "^6.0.0", + "proggy": "^4.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "semver": "^7.3.7", + "ssri": "^13.0.0", + "treeverse": "^3.0.0", + "walk-up-path": "^4.0.0" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/arborist/node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", + "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", + "dev": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", + "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "ini": "^6.0.0", + "lru-cache": "^11.2.1", + "npm-pick-manifest": "^11.0.1", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git/node_modules/ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", + "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^5.0.0", + "npm-normalize-package-bin": "^5.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/map-workspaces": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-5.0.3.tgz", + "integrity": "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "glob": "^13.0.0", + "minimatch": "^10.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/metavuln-calculator": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-9.0.3.tgz", + "integrity": "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cacache": "^20.0.0", + "json-parse-even-better-errors": "^5.0.0", + "pacote": "^21.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-4.0.0.tgz", + "integrity": "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", + "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", + "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^7.0.0", + "glob": "^13.0.0", + "hosted-git-info": "^9.0.0", + "json-parse-even-better-errors": "^5.0.0", + "proc-log": "^6.0.0", + "semver": "^7.5.3", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/package-json/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-5.0.0.tgz", + "integrity": "sha512-8TZWfTQOsODpLqo9SVhVjHovmKXNpevHU0gO9e+y4V4fRIOneiXy0u0sMP9LmS71XivrEWfZWg50ReH4WRT4aQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/redact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", + "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", + "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "node-gyp": "^12.1.0", + "proc-log": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@oxc-project/types": { + "version": "0.154.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.154.0.tgz", + "integrity": "sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==", + "devOptional": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/@pinia/testing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-2.0.1.tgz", + "integrity": "sha512-pQ4a4SCzdiLrhM4yv/TQG2ufNmktNlLZjjN6X/qMhXvZIiDN3L4L4WrChmcufX2LIarbl/ZPWOty1RB5KZIb2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "nostics": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "pinia": ">=4.0.2" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/npm-conf": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.3.tgz", + "integrity": "sha512-//0sR/cow/s4ICQaYoAobOl4aU8cjU6x/V24V7XkKotb9+O+3zySIYp146vpaobYHnxa4pZX8NkV54Z5AwbDKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "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==", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.14.tgz", + "integrity": "sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.14.tgz", + "integrity": "sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.14.tgz", + "integrity": "sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.14.tgz", + "integrity": "sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.14.tgz", + "integrity": "sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.14.tgz", + "integrity": "sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.14.tgz", + "integrity": "sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.14.tgz", + "integrity": "sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.14.tgz", + "integrity": "sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.14.tgz", + "integrity": "sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.14.tgz", + "integrity": "sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.14.tgz", + "integrity": "sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.14.tgz", + "integrity": "sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.14.tgz", + "integrity": "sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.14.tgz", + "integrity": "sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sigstore/bundle": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", + "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.1.tgz", + "integrity": "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.2.tgz", + "integrity": "sha512-SQqvFMt4V78fdjcDdYX6HbiVSOR4QK3ZgwCa2KOsopAgPIHy1rU5UDUmzLl02r5oyyaYcYHR1hpwDRk/yUe+Mw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", + "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@gar/promise-retry": "^1.0.2", + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.2.0", + "@sigstore/protobuf-specs": "^0.5.0", + "make-fetch-happen": "^15.0.4", + "proc-log": "^6.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", + "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.5.0", + "tuf-js": "^4.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.1.tgz", + "integrity": "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.2.1", + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@simple-git/args-pathspec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@simple-git/args-pathspec/-/args-pathspec-1.0.4.tgz", + "integrity": "sha512-EtMX6XjRWSastG2SdkmSQByPtJ9dx/NIjnHbpQPCYt62j4RmSx5rgLTGpw0YCjF5h191gZOmBfheOT23cRSFdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@simple-git/argv-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@simple-git/argv-parser/-/argv-parser-1.1.1.tgz", + "integrity": "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-git/args-pathspec": "^1.0.3" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.19.6", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.19.6.tgz", + "integrity": "sha512-CsTW892z23gy7IyxYTTorVu1uZWB+0N349rSMgKz4rFLPpLza7F7TpcCKeI5iUAwYQCt8QUlOU67J+KXCxtpGw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/vue-virtual": { + "version": "3.13.47", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.47.tgz", + "integrity": "sha512-6HzdYK9bDyDoD9Q/NjepnC4wGDaZ7mFl5zz8tbn3Fmy7FDicI98ZJ+R37ztFssnoTMoCQhY3GfUhlz+pW/vOTg==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.19.6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.0.0" + } + }, + "node_modules/@tsconfig/node18": { + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.7.tgz", + "integrity": "sha512-UyenTORreCUh8MKh2qbLGGHTRrxjBbSwvX0ZoWs6Jx1jrNS62PXEA3+VaLvmb0YDQrgGU3v3h7zB9Xs/BN1ozg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", + "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^10.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz", + "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@types/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.26", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.26.tgz", + "integrity": "sha512-48NWfiY6oNcKOh47Z4h+sIvwcQR91h6KPhaYKgeMIrkT2jV82Gy90SErj60vW8jQbeMSOSbhIv3bZ7JoqPPVhA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-iG0T6+nYJ9FAPmx9SsUlnwcq1ZVRuCXcVEvWnntoPlrOpwtSTKNDC9uVAxTsC3PUvJ+99n4RpAcNgBbHX3JSnQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/vinyl": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-67MQl+fpWKVTT1NYdnmo3U4sc/xPo/zQBncVnI74qmQa0z/b+1g6iYqNmGCPbxO+zz2aklb08a0oHfegiVd0/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz", + "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/type-utils": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.68.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.13.tgz", + "integrity": "sha512-2E8Q6rh+1RRSq/YdaGsNfXsEZy9FVqv6BSSrkmZJP7BnaoPnRfKL+YaofPvP+5rzdk144qSm6i4+hvPgUcbV4Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz", + "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz", + "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.68.0", + "@typescript-eslint/types": "^8.68.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz", + "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz", + "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz", + "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.0.tgz", + "integrity": "sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz", + "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.68.0", + "@typescript-eslint/tsconfig-utils": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz", + "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz", + "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", + "integrity": "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz", + "integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.11", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.11", + "vitest": "4.1.11" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.11", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.11", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.11", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vue-macros/common": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.4.tgz", + "integrity": "sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-sfc": "^3.5.22", + "ast-kit": "^2.1.2", + "local-pkg": "^1.1.2", + "magic-string-ast": "^1.0.2", + "unplugin-utils": "^0.3.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/vue-macros" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.2.25" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.44.tgz", + "integrity": "sha512-k34nCytbK8PQ1gR2mGROYOw6Pnv/mumqIdrZ3x2tbyXZDWm7ViKGLTfdB+DRrWqEQsLgGJvn0WN9jBif5zCTLQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.29.9", + "@vue/shared": "3.5.44", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.2" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.44.tgz", + "integrity": "sha512-W5AoBFWdw1lQAKiHowkfgFKFab82oSRT6sGsPfw/q1GRjsy/ZJFLHGhJyBRIFN9APLTUduDH9U2JAiPOIyKuYg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-core": "3.5.44", + "@vue/shared": "3.5.44" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.41.tgz", + "integrity": "sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.41", + "@vue/compiler-dom": "3.5.41", + "@vue/compiler-ssr": "3.5.41", + "@vue/shared": "3.5.41", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/@vue/compiler-core": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.41.tgz", + "integrity": "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.41", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/@vue/compiler-dom": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.41.tgz", + "integrity": "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.41.tgz", + "integrity": "sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/compiler-ssr/node_modules/@vue/compiler-core": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.41.tgz", + "integrity": "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.41", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr/node_modules/@vue/compiler-dom": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.41.tgz", + "integrity": "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/compiler-ssr/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@vue/devtools-api": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", + "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.2.1" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", + "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.2.1", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", + "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.41.tgz", + "integrity": "sha512-rznsqKM0np0x18EjzF8x88MpEhdNsffbvFbckLL5+oUKz1BxAImEmO7J1ArRYSyo6aQaVoBDp7jEkT91OOxydA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/reactivity/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.41.tgz", + "integrity": "sha512-Vcry58hiAKwGen9Z1jUZE0feFsNArPCMOImYI8el48A9Idf6DuQYD0U05zZIF2Iad1hGhPSvcbBbAOhNr55fhg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/runtime-core/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.41.tgz", + "integrity": "sha512-3vVBahVBS9+U6cmXBLyb8nE6/yYo4J/CGI9eVFs3KiMc0YHuudwKyShTD65jtJy/L9PUUxNAFu4cj4LiJ0UFbw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.41", + "@vue/runtime-core": "3.5.41", + "@vue/shared": "3.5.41", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/runtime-dom/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.41.tgz", + "integrity": "sha512-n6hx/pNFfbD6SuyeuMVkvqox8bwf/ET9JlA/kAz/imw8sw++wkqKe2mHX5KutjPpbKE4Z56yTHszoOjGMI9igQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.41", + "@vue/runtime-dom": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/@vue/server-renderer/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/@vue/shared": { + "version": "3.5.44", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.44.tgz", + "integrity": "sha512-H82XLH0DjmSOdbEwO15x3QTo1f5PWEtv237eLpYKc0mqLu+B8hnq16lFWmuBmNurkeiG3wr+oM1FhOll/YVFRg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@vue/test-utils": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.11.tgz", + "integrity": "sha512-GDqaqZsA6m2E5vNzej0aYiIb6BX8xV9pNSbbbXKOfEYwg7ZNblVX8suyqmUBThq8VIrgAJNxn+z72hVtUeiWHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-beautify": "^1.14.9", + "vue-component-type-helpers": "^3.0.0" + }, + "peerDependencies": { + "@vue/compiler-dom": "3.x", + "@vue/server-renderer": "3.x", + "vue": "3.x" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + } + } + }, + "node_modules/@vue/tsconfig": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.9.1.tgz", + "integrity": "sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 5.8", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vuelidate/core": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vuelidate/core/-/core-2.0.3.tgz", + "integrity": "sha512-AN6l7KF7+mEfyWG0doT96z+47ljwPpZfi9/JrNMkOGLFv27XVZvKzRLXlmDPQjPl/wOB1GNnHuc54jlCLRNqGA==", + "license": "MIT", + "dependencies": { + "vue-demi": "^0.13.11" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^2.0.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vuelidate/core/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vuelidate/validators": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@vuelidate/validators/-/validators-2.0.4.tgz", + "integrity": "sha512-odTxtUZ2JpwwiQ10t0QWYJkkYrfd0SyFYhdHH44QQ1jDatlZgTh/KRzrWVmn/ib9Gq7H4hFD4e8ahoo5YlUlDw==", + "license": "MIT", + "dependencies": { + "vue-demi": "^0.13.11" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^2.0.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vuelidate/validators/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/core": { + "version": "14.4.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.4.0.tgz", + "integrity": "sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.4.0", + "@vueuse/shared": "14.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "14.4.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.4.0.tgz", + "integrity": "sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "14.4.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.4.0.tgz", + "integrity": "sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@yeoman/adapter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@yeoman/adapter/-/adapter-4.0.2.tgz", + "integrity": "sha512-4uttbNuZ/guMBRhf7R6TCfnLT6XY1HGpxsq6vpHRM3AVr5G6Qz7xXqxG2kdMzBGtIuH5CkXz0k/Byl27GsvIkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.5", + "@inquirer/prompts": "^8.3.0", + "chalk": "^5.6.2", + "inquirer": "^13.3.0", + "log-symbols": "^7.0.1", + "ora": "^9.3.0", + "p-queue": "^9.1.0", + "text-table": "^0.2.0" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@yeoman/conflicter": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@yeoman/conflicter/-/conflicter-4.1.0.tgz", + "integrity": "sha512-Py62rJdWHf1zMpf801Ql7kg+sbUeVmvfmZf++mgA1SOk/uByLIfcXUMDzQPSHkW4Y7I2yVWLKZATRGjoczXVFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yeoman/transform": "^2.1.1", + "binary-extensions": "^3.1.0", + "cli-table": "^0.3.11", + "dateformat": "^5.0.3", + "diff": "^9.0.0", + "isbinaryfile": "^5.0.4", + "mem-fs-editor": "^12.0.4", + "minimatch": "^10.2.5", + "p-transform": "^5.0.1", + "pretty-bytes": "^7.1.0", + "slash": "^5.1.0", + "textextensions": "^6.11.0" + }, + "acceptDependencies": { + "isbinaryfile": "^6.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "peerDependencies": { + "@types/node": ">=20.14.8", + "@yeoman/types": "^1.0.0", + "mem-fs": "^4.0.0" + } + }, + "node_modules/@yeoman/conflicter/node_modules/isbinaryfile": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@yeoman/namespace": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@yeoman/namespace/-/namespace-2.1.0.tgz", + "integrity": "sha512-/BxsZlALPRp34juAzzh9QUr2hR9w9o+dBSw8sF/iv7NfUU/A/QI0xOyVtQJz2uCPuvtY6nkGDxYxZoKI/lnFQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.13.0 || >=18.12.0" + } + }, + "node_modules/@yeoman/transform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@yeoman/transform/-/transform-2.1.2.tgz", + "integrity": "sha512-LdPNm5Moc+Z8l2YeQ0IzsybXoV531o7RmGJB8lpFr8SjtqqGkT2bZYlS1LftPpCcPJ//yE0MbI/fPGh1WWlabg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^9.0.9" + }, + "acceptDependencies": { + "minimatch": "^10.2.5" + }, + "engines": { + "node": ">=18.19.0" + }, + "peerDependencies": { + "@types/node": ">=18.19.44" + } + }, + "node_modules/@yeoman/types": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@yeoman/types/-/types-1.13.0.tgz", + "integrity": "sha512-M7+TSQWo8c2/P5nUdCJb1Y8yDBgcMyIeKxCxM+1JeTfXDvanBRPrD5GzdvgesUr3LCq+xtEqH2f31wkRjPWplg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.13.0 || >=18.12.0" + }, + "peerDependencies": { + "@types/node": ">=16.18.26", + "@yeoman/adapter": "^1.6.0 || ^2.0.0-beta.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "mem-fs": "^3.0.0 || ^4.0.0-beta.1" + }, + "peerDependenciesMeta": { + "@yeoman/adapter": { + "optional": true + }, + "mem-fs": { + "optional": 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, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/acorn": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.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==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.4.0.tgz", + "integrity": "sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/array-differ": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-4.0.0.tgz", + "integrity": "sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.7.tgz", + "integrity": "sha512-kFL68AG6ajd8fg248zwM9GQrUWEp79gsmjum34OEXjs4yHuUMZfYKwOLW9GMmB4oNvVrj+EAGxsP7ye2UR9UlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/ast-walker-scope": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.9.0.tgz", + "integrity": "sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@babel/types": "^7.29.0", + "ast-kit": "^2.2.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", + "integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.6", + "caniuse-lite": "^1.0.30001806", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "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.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axios-mock-adapter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-2.1.0.tgz", + "integrity": "sha512-AZUe4OjECGCNNssH8SOdtneiQELsqTsat3SQQCWLPjN436/H+L9AjWfV7bF+Zg/YL9cgbhrz5671hoh+Tbn98w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "is-buffer": "^2.0.5" + }, + "peerDependencies": { + "axios": ">= 0.17.0" + } + }, + "node_modules/b4a": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.9.0.tgz", + "integrity": "sha512-dpfcF9fDNR6++cthXR67iyhgqWy9CBouAvIWhIntzBG6cvK/cnIPiZQjBwi/ZqjjBEDGfoNDtmB0kTjroOJ3pQ==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bare-events": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.2.tgz", + "integrity": "sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.30", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.30.tgz", + "integrity": "sha512-YJs6Pz17RMNv8HoyKREtCY38E3BV1nPkWVmIb+XN1uHC1Vqt3KZCH/uJH9ZKRoiKb/icZ6tvehyee6RZNbFfRA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bin-links": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.2.tgz", + "integrity": "sha512-frE1t78WOwJ45PKV2cF2tNPjTcs9L1J9s6VkrV59wanRP4GlaomuxYPVma7BwthMg8WnfSory4w5PTE6FZZ81w==", + "dev": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "proc-log": "^6.0.0", + "read-cmd-shim": "^6.0.0", + "write-file-atomic": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/binary-extensions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-3.2.0.tgz", + "integrity": "sha512-DjR9rgAOMQn9TrUHzijJUtvoKviDRvFxuIyqZrubxHqRpQN9OzfXrrLivm7xb3q8oJSKsiuBor4bAS2wafLnVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/bootstrap": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/bootstrap-vue-next": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bootstrap-vue-next/-/bootstrap-vue-next-1.0.1.tgz", + "integrity": "sha512-3qIPlwy1T4nWwWTk1a9jHC7k60N94N1ZvF8sLqH6oIGWKsWa5wrDNxUiHRgApoF/aUjhXu3bjZqo/W7Fn0xi4w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/vue": "^2.0.1", + "@vueuse/core": "~14.2.1", + "reka-ui": "^2.10.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap-vue-next" + }, + "peerDependencies": { + "@floating-ui/vue": "*", + "@internationalized/date": "*", + "@vueuse/core": "*", + "@vueuse/integrations": "*", + "bootstrap": "^5.3.0", + "focus-trap": "*", + "reka-ui": "*", + "vue": "^3.5.13", + "vue-router": "*" + }, + "peerDependenciesMeta": { + "@floating-ui/vue": { + "optional": true + }, + "@internationalized/date": { + "optional": true + }, + "@vueuse/core": { + "optional": true + }, + "@vueuse/integrations": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "reka-ui": { + "optional": true + }, + "vue-router": { + "optional": true + } + } + }, + "node_modules/bootstrap-vue-next/node_modules/@vueuse/core": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz", + "integrity": "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.2.1", + "@vueuse/shared": "14.2.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/bootstrap-vue-next/node_modules/@vueuse/metadata": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.1.tgz", + "integrity": "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/bootstrap-vue-next/node_modules/@vueuse/shared": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.2.1.tgz", + "integrity": "sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.29.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.4.tgz", + "integrity": "sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.29", + "caniuse-lite": "^1.0.30001816", + "electron-to-chromium": "^1.5.459", + "node-releases": "^2.0.59", + "update-browserslist-db": "^1.3.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-image-size": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/buffer-image-size/-/buffer-image-size-0.6.4.tgz", + "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/cacache": { + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.4.tgz", + "integrity": "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^5.0.0", + "fs-minipass": "^3.0.0", + "glob": "^13.0.0", + "lru-cache": "^11.1.0", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^13.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/cacache/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001817", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001817.tgz", + "integrity": "sha512-uZ1JG80BwhtMalIAGPxPfmNhHyd/B/nTdr3hITWlRamSyAdUStP1Gop01e7SD5q6J90ixJvWDbvmiFVfDgn4bw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.3.0.tgz", + "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", + "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", + "dev": true, + "license": "MIT" + }, + "node_modules/chevrotain": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-13.2.0.tgz", + "integrity": "sha512-GTouk5YzgBxlTPCaDn5q0q2EJKkrYmnPF+HmF8v0Qo4r3iyPG7HJivkN1wthCXZcm3sIcZFpGTRovLPNdJNRCA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "13.2.0", + "@chevrotain/gast": "13.2.0", + "@chevrotain/regexp-to-ast": "13.2.0", + "@chevrotain/types": "13.2.0", + "@chevrotain/utils": "13.2.0" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "devOptional": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/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==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz", + "integrity": "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dev": true, + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "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, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cmd-shim": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-8.0.0.tgz", + "integrity": "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/comment-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.9.tgz", + "integrity": "sha512-+2AvZKjJaNq9GQljm3tr0utwrig5BL+jgJGvz5rDpGKNIp+ojcRXWUwBbh/sGIi1QCprR6PsKFakub+w1v+4hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/concurrently": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-10.0.5.tgz", + "integrity": "sha512-JaP/CoftUrCcAFW/g//RbgEGwlelnEae6cfBLgH6ZdO6s8jPkn6p9SB9u6pdVxYXoiSnFqseOlHfrEfF82TVOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "5.6.2", + "rxjs": "7.8.2", + "shell-quote": "1.9.0", + "supports-color": "10.2.2", + "tree-kill": "1.2.2", + "yargs": "18.0.0" + }, + "bin": { + "conc": "dist/bin/index.js", + "concurrently": "dist/bin/index.js" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/confbox": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.3.1.tgz", + "integrity": "sha512-cKUSoKa8YxFZZSmraVi7onONx3amu77ngK3kGpsYHDH7drPwCRkQE1RYMPlLRrMtnciRj274XNRxcHxnKmDSnA==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/dateformat": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.4.tgz", + "integrity": "sha512-DnMqBsxDYMXnJ1c6TY8AgalunEVV5LBm1INpkod2A60Ldw/bopC/MGH0bEoK0S+I66Juezz36snGuWrEp9FmNg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/dayjs": { + "version": "1.11.23", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.23.tgz", + "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-indent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.2.tgz", + "integrity": "sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/diff": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dockerfile-ast": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/dockerfile-ast/-/dockerfile-ast-0.7.1.tgz", + "integrity": "sha512-oX/A4I0EhSkGqrFv0YuvPkBUSYp1XiY8O8zAKc8Djglx8ocz+JfOr8gP0ryRMC2myqvDLagmnZaU9ot1vG2ijw==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-languageserver-textdocument": "^1.0.8", + "vscode-languageserver-types": "^3.17.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dot-properties": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/dot-properties/-/dot-properties-1.1.1.tgz", + "integrity": "sha512-2Pog+JtvYuFFmV9Dm1VA1yphW7DYyn41MHLhnzuviUlLFbRF2uxmh8sE+IbhcgogcUcmtmpzHzzebmeT7YEAXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/editorconfig": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.7.tgz", + "integrity": "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "^9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/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, + "license": "MIT" + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ejs": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-6.0.1.tgz", + "integrity": "sha512-UaaM14yby8U3k02ihS1Bmj5Kz2d7CCQM1scxpgs4Mhkq8F1wR2gl3+Ts4h5Ne4Mnt7M9m4Dw7jsuMr3+xO4vZA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.12.18" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.460", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.460.tgz", + "integrity": "sha512-rRaVC7bNUyGsL+GMtmZfv3AfgG6za7gE9v5bT0PIbjEerddA0IQ+tCK05NFAXqCpNlrxBZqbFqquyxHRQONHTA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-4.0.0.tgz", + "integrity": "sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-safe-filename": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.9.1.tgz", + "integrity": "sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==", + "dev": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-import-x": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.17.1.tgz", + "integrity": "sha512-4cdstYkKCyjumM2Q9NSI03K8D2a9F4Ssz33K2lv2hQa4KmR9jPLwk3uWGtNvclfqBrPGfGuMBwsGMbe6dMRbfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.56.0", + "comment-parser": "^1.4.1", + "debug": "^4.4.1", + "eslint-import-context": "^0.1.9", + "is-glob": "^4.0.3", + "minimatch": "^9.0.3 || ^10.1.2", + "semver": "^7.7.2", + "stable-hash-x": "^0.2.0", + "unrs-resolver": "^1.9.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-import-x" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "eslint-import-resolver-node": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/utils": { + "optional": true + }, + "eslint-import-resolver-node": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-java-lang": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-java-lang/-/eslint-plugin-java-lang-0.6.0.tgz", + "integrity": "sha512-DkRgwq940dd8U7egMxnchuBixkssqlh4iTZ7gbHTc2GOfhq8f1CC2/5kZH1J926aDbegRzS4bGYNSj5hbT3O4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "web-tree-sitter": "^0.26.8" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/marcelo-boveto-shima" + }, + "peerDependencies": { + "eslint": ">=9" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-unused-imports": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz", + "integrity": "sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^10.0.0 || ^9.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.10.0.tgz", + "integrity": "sha512-dL9x9rBHqqNcByWiLOHK6L0SB97V82/NC0cZRn9cXPjM7pCuWlpQQP9bFH4vjBv80ej1ZpzAkuD8zWH1o9bZbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^7.1.4", + "semver": "^7.8.5", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "vue-eslint-parser": "^10.3.0" + }, + "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, + "@typescript-eslint/parser": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/execa": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-10.0.1.tgz", + "integrity": "sha512-ge98qjkRK4IB7tL7Ju/6qmm5LHoH1eEMt5FNZrz3f4UIYhF28lggX20z3FaX1sgc67msLEn0N0BscOs29iuwyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "figures": "^6.1.0", + "get-stream": "^9.0.1", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.3.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "which-command": "^0.1.0", + "yoctocolors": "^2.1.2" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/exsolve": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.3.tgz", + "integrity": "sha512-kuzL9zherLQoqDeQaS55AiiIg1kb4KYXaSusTtgZTPlvKP2gGCI82LNmBNh5RjDVUXIcmgx+/Mx7vPwRzBbhJA==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, + "node_modules/fast-xml-builder": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.1.tgz", + "integrity": "sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.11.0.tgz", + "integrity": "sha512-9IGxMqvqLOnqP+Egi1nqDHKv5k8aZ7r9n558enxcucmyVGEBNPAU+MOg/8jPIS7rO7sSq4gFm1/nHtiaubMruw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^3.0.0", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.2", + "xml-naming": "^0.3.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/first-chunk-stream": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-5.0.0.tgz", + "integrity": "sha512-WdHo4ejd2cG2Dl+sLkW79SctU7mUQDfr4s1i26ffOZRs5mgv+BRttIM9gwcq0rDbemo0KlpVPaa3LBVLqPXzcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/fly-import": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fly-import/-/fly-import-1.2.0.tgz", + "integrity": "sha512-arbt5zds9QJ3QrH5cSu028M/3ThAjXhePRa5pjbO0cHi5ppWjwGTCPtTe5VRVwh6a7I9bwyMTYRAZlU2L2e0iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@npmcli/arborist": "^9.1.3", + "env-paths": "^4.0.0", + "npm-package-arg": "^13.0.2", + "registry-auth-token": "^5.1.0", + "registry-url": "^7.2.0", + "semver": "^7.8.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/fly-import/node_modules/ini": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/fly-import/node_modules/registry-url": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-7.2.0.tgz", + "integrity": "sha512-I5UEBQ+09LWKInA1fPswOMZps0cs2Z+IQXb5Z5EkTJiUmIN52Vm/FD3ji5X82c5jIXL3nWEWOrYK0RkON6Oqyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.1", + "ini": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz", + "integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "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, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "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, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-jhipster": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/generator-jhipster/-/generator-jhipster-9.3.0.tgz", + "integrity": "sha512-+tz3WN535ihK3MWm7HgqnX3PEkRWpSbI9VjBTaUp1Xm6w9ADhn3RLpxUKZOfrYRAa6zO8dBRFOFxElYpLopwJQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/js": "10.0.1", + "@faker-js/faker": "10.6.0", + "@iarna/toml": "3.0.0", + "@types/ejs": "3.1.5", + "@types/lodash-es": "4.17.12", + "@yeoman/adapter": "4.0.2", + "@yeoman/conflicter": "4.1.0", + "@yeoman/namespace": "2.1.0", + "@yeoman/transform": "2.1.2", + "@yeoman/types": "1.13.0", + "chalk": "6.0.0", + "chevrotain": "13.2.0", + "commander": "15.0.0", + "debug": "4.4.3", + "didyoumean": "1.2.2", + "dockerfile-ast": "0.7.1", + "dot-properties": "1.1.1", + "ejs": "6.0.1", + "eslint": "10.9.1", + "eslint-plugin-import-x": "4.17.1", + "eslint-plugin-java-lang": "0.6.0", + "eslint-plugin-unused-imports": "4.4.1", + "execa": "10.0.1", + "fast-xml-builder": "1.3.1", + "fast-xml-parser": "5.11.0", + "globals": "17.11.0", + "isbinaryfile": "5.0.0", + "latest-version": "9.0.0", + "lodash-es": "4.18.1", + "mem-fs": "4.1.5", + "mem-fs-editor": "12.0.8", + "minimatch": "10.2.6", + "os-locale": "8.0.0", + "p-transform": "5.0.1", + "parse-gitignore": "2.0.0", + "piscina": "5.3.1", + "pluralize": "8.0.0", + "prettier": "3.9.6", + "prettier-plugin-java": "2.10.3", + "prettier-plugin-packagejson": "3.0.2", + "prettier-plugin-properties": "0.3.1", + "randexp": "0.5.3", + "semver": "7.8.5", + "simple-git": "3.36.0", + "sort-keys": "6.0.1", + "tinyglobby": "0.2.17", + "type-fest": "5.8.0", + "typescript": "6.0.3", + "typescript-eslint": "8.68.0", + "yaml": "2.9.0", + "yeoman-environment": "6.2.0", + "yeoman-generator": "8.3.0" + }, + "bin": { + "jhipster": "dist/cli/jhipster.cjs" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0", + "npm": ">=10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/generator-jhipster" + }, + "peerDependencies": { + "yeoman-test": "11.6.0" + }, + "peerDependenciesMeta": { + "yeoman-test": { + "optional": true + } + } + }, + "node_modules/generator-jhipster/node_modules/chalk": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-6.0.0.tgz", + "integrity": "sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.7.0.tgz", + "integrity": "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/git-hooks-list": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.2.1.tgz", + "integrity": "sha512-WNvqJjOxxs/8ZP9+DWdwWJ7cDsd60NHf39XnD82pDVrKO5q7xfPqpkK6hwEAmBa/ZSEE4IOoR75EzbbIuwGlMw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/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, + "license": "MIT" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz", + "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.4.tgz", + "integrity": "sha512-c8B/VNLmxRcmqqenRA9t+9IyOjf9+V6lTxPaUJLqOCONdQkWZ0ETYgX0qbtJqPsgCNusT9MZ5Jeidw8Eb9tn2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "is-path-inside": "^4.0.0", + "micromatch": "^4.0.8", + "slash": "^5.1.0", + "unicorn-magic": "^0.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.13.tgz", + "integrity": "sha512-2E8Q6rh+1RRSq/YdaGsNfXsEZy9FVqv6BSSrkmZJP7BnaoPnRfKL+YaofPvP+5rzdk144qSm6i4+hvPgUcbV4Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/globby/node_modules/unicorn-magic": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.1.tgz", + "integrity": "sha512-lzlXPoVB0Uy/FvTaUgX39RbixYiSKoc3JSoSf01+0c2B6FR3qdYIPN7Qjo/AV7n6sqLCk0509cT3LRj1oSZ1+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "license": "ISC" + }, + "node_modules/grouped-queue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-2.1.0.tgz", + "integrity": "sha512-c5NDCWO0XiXuJAhOegMiNotkDmgORN+VNo3+YHMhWpoWG/u2+8im8byqsOe3/myI9YcC//plRdqGa2AE3Qsdjw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/happy-dom": { + "version": "20.11.6", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.11.6.tgz", + "integrity": "sha512-Hldbg8AdAa5a5oDcZpjqnGitp7JB0hqWmfv/8qr+kft4vzSD8BHsbdRfzYvL/0QcbKcURC/yyoygbeDQarPvYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "buffer-image-size": "^0.6.4", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.21.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/hosted-git-info": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "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, + "license": "MIT" + }, + "node_modules/http-cache-semantics": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz", + "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", + "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", + "dev": true, + "license": "ISC", + "dependencies": { + "minimatch": "^10.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/immutable": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.9.tgz", + "integrity": "sha512-ObHy4YN7ycwZOUCLI1/6svfyAFu7vL8RhAvVu/bh/RZW9EPlOyDaQ9jDQWCtdqzaXUjgXZCW1migtHE7YI7UGQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "13.4.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-13.4.3.tgz", + "integrity": "sha512-EPd3IqieHSavSOXh+LZhrIkdQcOELWeRblLT6kslQr+cF9XTh/HxZdSt1YkHH1iq4dvqBnV42uwg2YlorgOy6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.5", + "@inquirer/core": "^11.1.10", + "@inquirer/prompts": "^8.4.3", + "@inquirer/type": "^4.0.5", + "mute-stream": "^3.0.0", + "run-async": "^4.0.6", + "rxjs": "^7.8.2" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/ip-address": { + "version": "10.7.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.4.tgz", + "integrity": "sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-binary-path/node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "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" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-core-module": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-safe-filename": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-safe-filename/-/is-safe-filename-0.1.1.tgz", + "integrity": "sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.2.tgz", + "integrity": "sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz", + "integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.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, + "license": "ISC" + }, + "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, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "BSD-3-Clause", + "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/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/joi": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-18.3.0.tgz", + "integrity": "sha512-/RwAK4BAfzcdbdFg073tzq4/xhY6Q7lMd5AmjqTL6pu0QFJdEmtswgm8BvgwXvOKuPNYQ8XrdQrrW/gF65LiNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/address": "^5.1.1", + "@hapi/formula": "^3.0.2", + "@hapi/hoek": "^11.0.7", + "@hapi/pinpoint": "^2.0.1", + "@hapi/tlds": "^1.1.1", + "@hapi/topo": "^6.0.2", + "@standard-schema/spec": "^1.1.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-cookie": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz", + "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-nice": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=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" + ], + "license": "MIT" + }, + "node_modules/just-diff": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==", + "dev": true, + "license": "MIT" + }, + "node_modules/just-diff-apply": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/ky": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz", + "integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, + "node_modules/latest-version": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz", + "integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "package-json": "^10.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "devOptional": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lint-staged": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.3.0.tgz", + "integrity": "sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^4.0.5", + "string-argv": "^0.3.2", + "tinyexec": "^1.2.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=22.22.1" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + }, + "optionalDependencies": { + "yaml": "^2.9.0" + } + }, + "node_modules/local-pkg": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.2.1.tgz", + "integrity": "sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==", + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", + "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magic-string-ast": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/magic-string-ast/-/magic-string-ast-1.0.3.tgz", + "integrity": "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==", + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.19" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/magicast": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.5.tgz", + "integrity": "sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" + } + }, + "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, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-fetch-happen": { + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz", + "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/agent": "^4.0.0", + "@npmcli/redact": "^4.0.0", + "cacache": "^20.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^6.0.0", + "ssri": "^13.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mem-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-4.1.5.tgz", + "integrity": "sha512-6aWRo1jLo82ngo44tPQXjzINN7gvSNWhMU96I+O5nsJWdPi5vbUJWMTDGZDb/AVpCJRpaLGcFgrIBIpyk0DuUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "vinyl": "^3.0.1", + "vinyl-file": "^5.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@types/node": ">=18", + "@types/vinyl": "^2.0.12" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@types/vinyl": { + "optional": true + } + } + }, + "node_modules/mem-fs-editor": { + "version": "12.0.8", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-12.0.8.tgz", + "integrity": "sha512-+kCqJcfWxLwwAQL9sNGM6KFehhAxf+CpUbf4BTR61exES5jv1/JufZGM2/6menk9TyN6/XutgZCBa7dn87152g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ejs": "^3.1.5", + "@types/picomatch": "^4.0.2", + "binaryextensions": "^6.11.0", + "commondir": "^1.0.0", + "debug": "^4.4.3", + "deep-extend": "^0.6.0", + "ejs": "^6.0.1", + "isbinaryfile": "5.0.7", + "minimatch": "^10.2.5", + "multimatch": "^8.0.0", + "normalize-path": "^3.0.0", + "textextensions": "^6.11.0", + "tinyglobby": "^0.2.15", + "vinyl": "^3.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "peerDependencies": { + "@types/node": ">=20", + "mem-fs": "^4.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/mem-fs-editor/node_modules/isbinaryfile": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "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, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "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, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", + "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^2.0.0", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + }, + "optionalDependencies": { + "iconv-lite": "^0.7.2" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "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, + "license": "ISC", + "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, + "license": "ISC" + }, + "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, + "license": "ISC", + "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, + "license": "ISC", + "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, + "license": "ISC" + }, + "node_modules/minipass-sized": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", + "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "license": "MIT" + }, + "node_modules/multimatch": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-8.0.0.tgz", + "integrity": "sha512-0D10M2/MnEyvoog7tmozlpSqL3HEU1evxUFa3v1dsKYmBDFSP1dLSX4CH2rNjpQ+4Fps8GKmUkCwiKryaKqd9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-differ": "^4.0.0", + "array-union": "^3.0.1", + "minimatch": "^10.2.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mute-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.5.tgz", + "integrity": "sha512-NFMjXXkyodBJnRrM0A6qxFO1OLUbrYLDhP1ZLetlXnyx41gKOAmVyROibq85j7I8dda4aZMs9L7kmRvvjNf7Cg==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/node-gyp": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz", + "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp/node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp/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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.59", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.59.tgz", + "integrity": "sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "license": "ISC", + "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": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-8.0.0.tgz", + "integrity": "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^9.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.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==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nostics": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nostics/-/nostics-1.3.0.tgz", + "integrity": "sha512-wzRsrJwNlFbqIRQt8aCeL2WE8USip/uuvGSOZV1D02CxX8ABTMbw8IywKjH7yWHETMXbWJI4OBpihg9rmz2Vyg==", + "license": "MIT" + }, + "node_modules/npm-bundled": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", + "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^5.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-install-checks": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", + "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-package-arg": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", + "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-packlist": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", + "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", + "dev": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^8.0.0", + "proc-log": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", + "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "npm-package-arg": "^13.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", + "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^4.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^15.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^13.0.0", + "proc-log": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/obug": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz", + "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ohash": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.12.tgz", + "integrity": "sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==", + "license": "MIT" + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.1.tgz", + "integrity": "sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.6.2", + "cli-cursor": "^5.0.0", + "cli-spinners": "^3.2.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.1.0", + "log-symbols": "^7.0.1", + "stdin-discarder": "^0.3.2", + "string-width": "^8.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.3.0.tgz", + "integrity": "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-locale": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-8.0.0.tgz", + "integrity": "sha512-0hdyXRn0wSKMTHCo2CkPJdTKzIhg1Wb7DxJtkeD8M8rRXSwP2ZFRu4UiWBnkjPdRbL5X+AnUVXBE2SZOmkm3dg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.1.1.tgz", + "integrity": "sha512-6Lh3jQPLthYujSrlw6ccWXBGZTkoTCz27Hd92g79LH/kjAbgoEu0t442cCCNbegPSJsA0lwDX8z0bcKtkpA32g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.5.tgz", + "integrity": "sha512-Lki/zhXFVmDhesBUn/yHRLW9Bte7mE7xoFHzTR8sIomV7a2z+LxYAPkGvdfidNiu4fKSfjtawixxSHcZci5QcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.4", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.2.tgz", + "integrity": "sha512-prbX4Z3YszrFNgH+MW5Zoeq3baXrMtP/MQnFeET90UB/GtGcGDQ5Usg9OCy6ETjTTntOw1SL2z9fMPUppN3Guw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-transform": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/p-transform/-/p-transform-5.0.1.tgz", + "integrity": "sha512-tb3/zIwbU6Z9RMDxZM3/UsyL5LpIUQj7Drq7iXWG9ilPpzyGG28EEFRRrGTsxHf3sOSOiQEiwevQH/VWtHbZfg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/node": ">=18.19.0", + "p-queue": "^8.0.1" + }, + "engines": { + "node": ">=18.19.0" + } + }, + "node_modules/p-transform/node_modules/p-queue": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-transform/node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", + "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ky": "^1.2.0", + "registry-auth-token": "^5.0.2", + "registry-url": "^6.0.1", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pacote": { + "version": "21.5.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.5.1.tgz", + "integrity": "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/git": "^7.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^6.0.0", + "sigstore": "^4.0.0", + "ssri": "^13.0.0", + "tar": "^7.4.3" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/parse-conflict-json": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-5.0.1.tgz", + "integrity": "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^5.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/parse-gitignore": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-2.0.0.tgz", + "integrity": "sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.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, + "license": "MIT", + "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, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-4.0.3.tgz", + "integrity": "sha512-XMQqpvjgG7LMqVhhFUzKLT4KEbsYbfZZ0CZU9PgdFm1O2VKBmIkykL8+SfNhOaT7sR0wT6BEgKT0YNDYWgmVRA==", + "license": "MIT", + "dependencies": { + "nostics": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/devtools-api": "^8.1.5", + "typescript": ">=5.6.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "@vue/devtools-api": { + "optional": false + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/piscina": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.3.1.tgz", + "integrity": "sha512-LYbVUyHb5CzavqNgs64Uv+gHkrCdEt73kfPazdsJnndDSJiaEDIzMUIAHbtV3plzaoBUphZfXZCQKF01LHMgXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.x" + }, + "optionalDependencies": { + "@napi-rs/nice": "^1.0.4" + } + }, + "node_modules/pkg-types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.4.0.tgz", + "integrity": "sha512-07Fys7iVx0X6TcviMOgogM1Lk33ZyqOezMnU79S+kffWqwolG/5W9V8EgQSeYCIfFTYVgssRbnH630Oa2+soBA==", + "license": "MIT", + "dependencies": { + "confbox": "^0.3.1", + "exsolve": "^1.1.3", + "pathe": "^2.0.3" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", + "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.20", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-17.0.0.tgz", + "integrity": "sha512-qzVMJhcq39KweT7Fp0HcjE5YxL5yI854Q3CtufxDuZKO9HLQUp2rptB9+U0MIj3pT1ZEVXoqnpeC1mSkfYuz4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=22.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.6.tgz", + "integrity": "sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-url": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.4.tgz", + "integrity": "sha512-/oBzyLOHQvXvVr/7bzZOFD5lYTy1nomVE4aMA9eY5KQsHfWLDIzb86q8XoUsmrj2xKoGYMAvd884EzJEQzuXIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "make-dir": "~3.1.0", + "mime": "~2.5.2", + "minimatch": "^3.1.5", + "xxhashjs": "~0.2.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-url/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, + "license": "MIT" + }, + "node_modules/postcss-url/node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/postcss-url/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, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss-url/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/postcss-url/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "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, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-java": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-2.10.3.tgz", + "integrity": "sha512-/g52mTbsN2ee8JjLRpBWGGmcmRhdv2zRWyj4QbsL9CQ+nKR022GRJhebwEpRyaCc8hLV6aO3JPGNQyXp1DPrCA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "web-tree-sitter": "0.26.11" + }, + "peerDependencies": { + "prettier": "^3.0.0" + } + }, + "node_modules/prettier-plugin-java/node_modules/web-tree-sitter": { + "version": "0.26.11", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.26.11.tgz", + "integrity": "sha512-Q5Dm3YTIXSXuH6FxX6RuzX2Qwpc4DPGiYMU87Wg5Z8OIStiQFiUex4zMDc0vBTw78EphaYJacncJghCHzbZptg==", + "dev": true, + "license": "MIT" + }, + "node_modules/prettier-plugin-packagejson": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-3.0.2.tgz", + "integrity": "sha512-kmoj3hEynXwoHDo8ZhmWAIjRBoQWCDUVackiWfSDWdgD0rS3LGB61T9zoVbume/cotYdCoadUh4sqViAmXvpBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "sort-package-json": "^3.6.0" + }, + "peerDependencies": { + "prettier": "^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/prettier-plugin-properties": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-properties/-/prettier-plugin-properties-0.3.1.tgz", + "integrity": "sha512-TE85dg+1ED7Dnz8lJqrlT9qXh7EKftrvmZgXwRC6jYT0/Ru2MlGkmvLDRUwoAGNaDCn8ijNjw0T33q6nVXgQ4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-properties": "^1.1.0" + }, + "peerDependencies": { + "prettier": ">= 2.3.0" + } + }, + "node_modules/pretty-bytes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-7.2.0.tgz", + "integrity": "sha512-T2kroepGB5DRVbkN/nOpW03+VRWqdtJhZNuCW3wYk3chdPjgi4GcTBOaxWfHq1MIM0ypidxsSWbQaAiRpxnXmg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-ms": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.1.tgz", + "integrity": "sha512-HzMy3Geq23nVALD/M2LliU+F+M+gVNsvkQWWqeBZ8HDiCgzo6YPJ/Omrmtq24EFrIsk0a3EkQGEd7bDOo+IhGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/proggy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/proggy/-/proggy-4.0.0.tgz", + "integrity": "sha512-MbA4R+WQT76ZBm/5JUpV9yqcJt92175+Y0Bodg3HgiXzrmKu7Ggq+bpn6y6wHH+gN9NcyKn3yg1+d47VaKwNAQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/promise-all-reject-late": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-call-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-3.0.2.tgz", + "integrity": "sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "drange": "^1.0.2", + "ret": "^0.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/read-cache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.2.tgz", + "integrity": "sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/read-cmd-shim": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-6.0.0.tgz", + "integrity": "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/read-package-up": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-12.0.0.tgz", + "integrity": "sha512-Q5hMVBYur/eQNWDdbF4/Wqqr9Bjvtrw2kjGxxBbKLbx8bVCL8gcArjTy8zDUuLGQicftpMuU0riQNcAsbtOVsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.1", + "read-pkg": "^10.0.0", + "type-fest": "^5.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-10.1.0.tgz", + "integrity": "sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.4", + "normalize-package-data": "^8.0.0", + "parse-json": "^8.3.0", + "type-fest": "^5.4.4", + "unicorn-magic": "^0.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.1.tgz", + "integrity": "sha512-lzlXPoVB0Uy/FvTaUgX39RbixYiSKoc3JSoSf01+0c2B6FR3qdYIPN7Qjo/AV7n6sqLCk0509cT3LRj1oSZ1+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz", + "integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^3.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reka-ui": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.11.0.tgz", + "integrity": "sha512-ilkpm4bIAol4jwzm4tpm3WVcffyGOpqksNZL1k1qO9QmIwAA+q8jroxjkUGLEn/GddfdExFfvofWfQiKZszUeQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/vue": "^2.0.1", + "@internationalized/date": "^3.5.0", + "@internationalized/number": "^3.5.0", + "@tanstack/vue-virtual": "^3.12.0", + "@vueuse/core": "^14.1.0", + "@vueuse/shared": "^14.1.0", + "aria-hidden": "^1.2.4", + "defu": "^6.1.5", + "ohash": "^2.0.11" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/zernonia" + }, + "peerDependencies": { + "vue": ">= 3.4.0" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "license": "ISC" + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/resolve": { + "version": "1.22.13", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", + "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.17.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/rimraf/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rolldown": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.14.tgz", + "integrity": "sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.154.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.14", + "@rolldown/binding-android-arm64": "1.2.14", + "@rolldown/binding-darwin-arm64": "1.2.14", + "@rolldown/binding-darwin-x64": "1.2.14", + "@rolldown/binding-freebsd-x64": "1.2.14", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.14", + "@rolldown/binding-linux-arm64-gnu": "1.2.14", + "@rolldown/binding-linux-arm64-musl": "1.2.14", + "@rolldown/binding-linux-ppc64-gnu": "1.2.14", + "@rolldown/binding-linux-s390x-gnu": "1.2.14", + "@rolldown/binding-linux-x64-gnu": "1.2.14", + "@rolldown/binding-linux-x64-musl": "1.2.14", + "@rolldown/binding-openharmony-arm64": "1.2.14", + "@rolldown/binding-win32-arm64-msvc": "1.2.14", + "@rolldown/binding-win32-x64-msvc": "1.2.14" + } + }, + "node_modules/run-async": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz", + "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==", + "dev": true, + "license": "MIT", + "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" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "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, + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.70.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", + "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", + "devOptional": true, + "license": "MIT", + "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/scule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz", + "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", + "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sigstore": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz", + "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.2.1", + "@sigstore/protobuf-specs": "^0.5.0", + "@sigstore/sign": "^4.1.1", + "@sigstore/tuf": "^4.0.2", + "@sigstore/verify": "^3.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/simple-git": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.36.0.tgz", + "integrity": "sha512-cGQjLjK8bxJw4QuYT7gxHw3/IouVESbhahSsHrX97MzCL1gu2u7oy38W6L2ZIGECEfIBG4BabsWDPjBxJENv9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "@simple-git/args-pathspec": "^1.0.3", + "@simple-git/argv-parser": "^1.1.0", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.10.tgz", + "integrity": "sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/sort-keys": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-6.0.1.tgz", + "integrity": "sha512-w7xWRu8U9MneKNna8ptG194jp9PLtbd/Rl6gwrmbK4yUeKbE66a64rHgl0iKTBBDr/hpanx7zMGP1Qo8MRkc/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-obj": "^4.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-object-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-2.1.0.tgz", + "integrity": "sha512-SOiEnthkJKPv2L6ec6HMwhUcN0/lppkeYuN1x63PbyPRrgSPIuBJCiYxYyvWRTtjMlOi14vQUCGUJqS6PLVm8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.7.1.tgz", + "integrity": "sha512-ssk1HG7whF8N/T1IsNAQrtHG5Cbdi0rAgRJZXYBr9hF5xaHnBNzUx/W6LcthEW7FhOwvZssbESZuO+GxssqAyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.2", + "detect-newline": "^4.0.1", + "git-hooks-list": "^4.1.1", + "is-plain-obj": "^4.1.0", + "semver": "^7.7.3", + "sort-object-keys": "^2.0.1", + "tinyglobby": "^0.2.15" + }, + "bin": { + "sort-package-json": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "license": "BSD-3-Clause", + "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, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/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, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.24.tgz", + "integrity": "sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/ssri": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", + "integrity": "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", + "dev": true, + "license": "MIT" + }, + "node_modules/stdin-discarder": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.3.2.tgz", + "integrity": "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/streamx": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.1.tgz", + "integrity": "sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.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, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-buf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-3.0.1.tgz", + "integrity": "sha512-iJaWw2WroigLHzQysdc5WWeUc99p7ea7AEgB6JkY8CMyiO1yTVAA1gIlJJgORElUIR+lcZJkNl1OGChMhvc2Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-utf8": "^0.2.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-bom-stream": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-5.0.0.tgz", + "integrity": "sha512-Yo472mU+3smhzqeKlIxClre4s4pwtYZEvDNQvY/sJpnChdaxmKuwU28UVx/v1ORKNMxkmj1GBuvxJQyBk6wYMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "first-chunk-stream": "^5.0.0", + "strip-bom-buf": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.5.1.tgz", + "integrity": "sha512-UM4nTLWzQiDBseVxUGxN0wJzIk0UU89Qi7pKXz9qISo+lhviJikTuikBsK/oFRlpvYHvSdz0TVoLyQ+sEpYwxA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" + } + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.32.14", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.32.14.tgz", + "integrity": "sha512-nOA2pSQhcmODMUQZpJHYKNuwniDUqcOWGNaSCOoZv12FdOSJ9JxV95HtyRGNMqEBj6h6lCNTy20TgZDYTSuUIg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, + "node_modules/synckit": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz", + "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.2.0.tgz", + "integrity": "sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "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, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/treeverse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tuf-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", + "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.8.0.tgz", + "integrity": "sha512-YGYEVz3Fm5iy/AybuA0oyNFq7H4CgQNfRp/qfe8nurE1kuCeNm3/vfm9X4Mtl+qLyaKJUh5xrFZwogr41SMjYA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.68.0.tgz", + "integrity": "sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.68.0", + "@typescript-eslint/parser": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/undici": { + "version": "6.29.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.1.tgz", + "integrity": "sha512-EvRlUt/QqAEvXdQeRMYUfwOQsfzpDztykrG2owGEE/rBOBoYv9uF39ZzsNDh4lTFHhTr2XOZjKkYgueD12ZmGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unplugin": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.4.0.tgz", + "integrity": "sha512-9skdIFlCsPdFV7wUfZxNsFInlW+7nJmGu2gkTu0OUhF56aXGsHab9x52/QhdJ4lC7ZDPWTxbiC4ANqVlsuaW3w==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "picomatch": "^4.0.7", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@farmfe/core": "*", + "@rsbuild/core": "*", + "@rspack/core": "*", + "bun-types-no-globals": "*", + "esbuild": "*", + "rolldown": "*", + "rollup": "*", + "unloader": "*", + "vite": "*", + "webpack": "*" + }, + "peerDependenciesMeta": { + "@farmfe/core": { + "optional": true + }, + "@rsbuild/core": { + "optional": true + }, + "@rspack/core": { + "optional": true + }, + "bun-types-no-globals": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "rolldown": { + "optional": true + }, + "rollup": { + "optional": true + }, + "unloader": { + "optional": true + }, + "vite": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/unplugin-utils": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.2.tgz", + "integrity": "sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==", + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/untildify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-6.0.0.tgz", + "integrity": "sha512-sA2YTBvW2F463GvSbiZtso+dpuQV+B7xX9saX30SGrR5Fyx4AUcvA/zN+ShAkABKUKVyDaHECsJrHv5ToTuHsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "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, + "license": "MIT" + }, + "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, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-license/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, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", + "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-file": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-5.0.0.tgz", + "integrity": "sha512-MvkPF/yA1EX7c6p+juVIvp9+Lxp70YUfNKzEWeHMKpUNVSnTZh2coaOqLxI0pmOe2V9nB+OkgFaMDkodaJUyGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/vinyl": "^2.0.7", + "strip-bom-buf": "^3.0.1", + "strip-bom-stream": "^5.0.0", + "vinyl": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vite": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-static-copy": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-4.1.1.tgz", + "integrity": "sha512-GrlA8YklrAfSyxJ4M3fdQLOo9oNkp56IM9FYgX/WtEgeIFkPwhu4wzpufBCIuNKCa6Fn77FkRdYxkHqV0FwjAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.6.0", + "p-map": "^7.0.4", + "picocolors": "^1.1.1", + "tinyglobby": "^0.2.17" + }, + "engines": { + "node": "^22.0.0 || >=24.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/sapphi-red" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/vitest": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest-sonar-reporter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vitest-sonar-reporter/-/vitest-sonar-reporter-3.0.0.tgz", + "integrity": "sha512-QRT5m9Z/3Kt0WVDVcFHm5LC9Ba89yDP4twlX2QUAJ9PdqfJBkLAh/kXj7m6U3i0k6GxnIEiwCc295bmAYokmZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "vitest": ">=3" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.15.tgz", + "integrity": "sha512-Gsfr9S8LU3S6885cS+NaleasJ0n3V5y/SOTqHCifQiXWFw3G9w9/YItDfwHrlCz+dSZWWZ8ilYVMcJe7Sz7Sxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.4.tgz", + "integrity": "sha512-nQsacoiijvl0fRf2q28uFDrAVwRhdCa3QveiF7/CX0r18mLR5FU/1WskSsCKOjmEbtteKUnY8x8Yzxop+k0zwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.41.tgz", + "integrity": "sha512-2laE0p+aK+/AOPG/XL/WepOs/GlK755LJ1XECi9kDUrz1FKNw8rb2Xzlw9JS1rqEV55nb0ttsKxVlTCcd+R5cg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.41", + "@vue/compiler-sfc": "3.5.41", + "@vue/runtime-dom": "3.5.41", + "@vue/server-renderer": "3.5.41", + "@vue/shared": "3.5.41" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-component-type-helpers": { + "version": "3.3.13", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.13.tgz", + "integrity": "sha512-02KCxSmKDhIITjKyJ4QT5csP6L0WoRborLqY/34a40+S9uvMvdNgMV0yVjO3p2Gkz3ZoPmFz/0JsGHacwJYTxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue-eslint-parser": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.1.tgz", + "integrity": "sha512-Gk6gRDj0n/fkRa3C3l0bBheoBckUq/Rs0F/TvMWIS6nzzx67amAViMe9CkNgsP2tXyQONvGiHQESHwFtZ3aYDA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0 || ^9.0.0", + "eslint-visitor-keys": "^4.2.0 || ^5.0.0", + "espree": "^10.3.0 || ^11.0.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/vue-i18n": { + "version": "11.4.9", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.4.9.tgz", + "integrity": "sha512-SJoEYcmt+g8IW1Ro9zuF6GyYEi/2t4kYlg0y7bUPKAyciR4Zhg6f+RTxgEZ9H2o9LrxJdcr50OH2OkGweRzRiA==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.4.9", + "@intlify/devtools-types": "11.4.9", + "@intlify/shared": "11.4.9", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-i18n/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.2.0.tgz", + "integrity": "sha512-QAC5i0LEb1GLG0LXDQmHu8L7FX12j0KwU/JTKmLQUJMrn04gQdKP6Du+p0QwpHb3iy71vBlqnHQ8WAfOSAWhqw==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^8.0.0", + "@vue-macros/common": "^3.1.3", + "@vue/devtools-api": "^8.1.5", + "ast-walker-scope": "^0.9.0", + "chokidar": "^5.0.0", + "json5": "^2.2.3", + "local-pkg": "^1.2.1", + "magic-string": "^0.30.21", + "mlly": "^1.8.2", + "muggle-string": "^0.4.1", + "nostics": "^1.1.4", + "pathe": "^2.0.3", + "picomatch": "^4.0.5", + "scule": "^1.3.0", + "tinyglobby": "^0.2.17", + "unplugin": "^3.3.0", + "unplugin-utils": "^0.3.2", + "yaml": "^2.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@pinia/colada": ">=0.21.2", + "@vue/compiler-sfc": "^3.5.34 || ^4.0.0", + "pinia": "^3.0.4 || ^4.0.2", + "vite": "^7.3.0 || ^8.0.0", + "vue": "^3.5.34 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@pinia/colada": { + "optional": true + }, + "@vue/compiler-sfc": { + "optional": true + }, + "pinia": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vue-router/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/vue-router/node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/vue/node_modules/@vue/compiler-core": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.41.tgz", + "integrity": "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.41", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/vue/node_modules/@vue/compiler-dom": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.41.tgz", + "integrity": "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.41", + "@vue/shared": "3.5.41" + } + }, + "node_modules/vue/node_modules/@vue/shared": { + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", + "license": "MIT" + }, + "node_modules/wait-on": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-9.1.0.tgz", + "integrity": "sha512-PymrLXHLBM1Ju/Xspb2ADUhbPSMvbnuNvy/mN2hWtpbJ3da0h3Ky1LqwKPG5QSVR57liyO0iUpfipYl/s5qNvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.18.1", + "joi": "^18.2.3", + "lodash": "^4.18.1", + "minimist": "^1.2.8", + "rxjs": "^7.8.2" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/web-tree-sitter": { + "version": "0.26.13", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.26.13.tgz", + "integrity": "sha512-5bUZ7vbQ1kcondet96wzP974+JfCZDeQ7bTpacICm2nnvHpa5cO0ByRsoMcAhUP+743vpkb4m0BFlVSm+Ye9VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "license": "MIT" + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-command": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/which-command/-/which-command-0.1.0.tgz", + "integrity": "sha512-XZyoF5/5hZtXitIwzrU4NKK+Wtbb9aB9CezUEw2Q0wlYK8NUYQxC1rRXgNueYLtBAJwXIb+/tFVk4dozciNJMA==", + "dev": true, + "license": "MIT", + "bin": { + "which-command": "cli.js" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/sindresorhus/which-command?sponsor=1" + } + }, + "node_modules/which-package-manager": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-package-manager/-/which-package-manager-1.0.1.tgz", + "integrity": "sha512-Nse2rVsL302dkEhCyyS1U3iEQ9FRYPPkWJNk188xUVkKIGXjMmDPlA3L1VettE+T2z7SGLsJiDaZw//8CHUQwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^7.0.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which-package-manager/node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/which-package-manager/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, + "license": "MIT", + "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/which-package-manager/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, + "license": "MIT", + "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/which-package-manager/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, + "license": "MIT", + "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/which-package-manager/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, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/which-package-manager/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/which-package-manager/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "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/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==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/write-file-atomic": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", + "dev": true, + "license": "ISC", + "dependencies": { + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/ws": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "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/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cuint": "^0.2.2" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-environment": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-6.2.0.tgz", + "integrity": "sha512-n4V0tM8zKKMldJvdqOA54SGcO3Al5N1ISUuDI5QmE5Li5NdH8VJr2wafjaPr+qe/ID1ZjnY99vQNkmF3JVd/qA==", + "dev": true, + "license": "BSD-2-Clause", + "workspaces": [ + "test/generators" + ], + "dependencies": { + "@yeoman/adapter": "^4.0.2", + "@yeoman/conflicter": "^4.1.0", + "@yeoman/namespace": "^2.1.0", + "@yeoman/transform": "^2.1.1", + "@yeoman/types": "^1.11.1", + "arrify": "^3.0.0", + "chalk": "^5.6.2", + "commander": "^14.0.3", + "debug": "^4.4.3", + "execa": "^9.6.1", + "fly-import": "^1.0.0", + "globby": "^16.2.0", + "grouped-queue": "^2.1.0", + "locate-path": "^8.0.0", + "lodash-es": "^4.18.1", + "mem-fs": "^4.1.4", + "mem-fs-editor": "^12.0.4", + "semver": "^7.7.4", + "slash": "^5.1.0", + "untildify": "^6.0.0", + "which-package-manager": "^1.0.1" + }, + "acceptDependencies": { + "@yeoman/adapter": ">=4.0.2" + }, + "bin": { + "yoe": "bin/bin.cjs" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + }, + "peerDependencies": { + "@yeoman/adapter": "^4.0.2", + "@yeoman/types": "^1.10.3", + "mem-fs": "^4.1.4" + } + }, + "node_modules/yeoman-environment/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/yeoman-environment/node_modules/execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/yeoman-environment/node_modules/locate-path": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-8.0.0.tgz", + "integrity": "sha512-XT9ewWAC43tiAV7xDAPflMkG0qOPn2QjHqlgX8FOqmWa/rxnyYDulF9T0F7tRy1u+TVTmK/M//6VIOye+2zDXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-environment/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, + "license": "MIT", + "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/yeoman-environment/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, + "license": "MIT", + "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/yeoman-environment/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-generator": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-8.3.0.tgz", + "integrity": "sha512-stpxbDj2KQj4CysTd15z51uMJmfXdTzvlQ9TSMwZxVaN5NJ6a0zWMX84GNx+bEhntZs6FoFS5Hnkdck4NRyu1g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/debug": "^4.1.13", + "@types/lodash-es": "^4.17.12", + "@yeoman/namespace": "^2.1.0", + "chalk": "^5.6.2", + "debug": "^4.4.3", + "execa": "^9.6.1", + "latest-version": "^9.0.0", + "lodash-es": "^4.18.1", + "mem-fs-editor": "^12.0.4", + "minimist": "^1.2.8", + "read-package-up": "^12.0.0", + "semver": "^7.7.4", + "simple-git": "^3.36.0", + "sort-keys": "^6.0.0", + "text-table": "^0.2.0", + "type-fest": "^5.6.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + }, + "peerDependencies": { + "@types/node": ">=20.19.35", + "@yeoman/types": "^1.1.1", + "mem-fs": "^4.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/yeoman-generator/node_modules/execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.2.0.tgz", + "integrity": "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/question-bank.jdl b/question-bank.jdl new file mode 100644 index 0000000..ed0e8b8 --- /dev/null +++ b/question-bank.jdl @@ -0,0 +1,62 @@ +enum OptionKey { + A, + B, + C, + D +} + +enum AttemptStatus { + IN_PROGRESS, + SUBMITTED +} + +entity Subject { + name String required minlength(2) maxlength(100), + description String maxlength(1000), + active Boolean required +} + +entity Question { + prompt String required minlength(5) maxlength(2000), + explanation String maxlength(2000), + active Boolean required +} + +entity Choice { + optionKey OptionKey required, + content String required maxlength(500), + displayOrder Integer required min(1) max(4), + correct Boolean required +} + +entity ExamAttempt { + startedAt Instant required, + submittedAt Instant, + status AttemptStatus required, + score Integer min(0) +} + +entity ExamAnswer { + questionTextSnapshot String required maxlength(2000), + explanationSnapshot String maxlength(2000), + selectedOption OptionKey, + selectedContentSnapshot String maxlength(500), + correct Boolean, + awardedPoints Integer min(0) +} + +relationship OneToMany { + Question{choice} to Choice{question required} + ExamAttempt{answer} to ExamAnswer{attempt required} +} + +relationship ManyToOne { + Question{subject(name) required} to Subject + ExamAttempt{subject(name) required} to Subject + ExamAttempt{user(login) required} to User with builtInEntity + ExamAnswer{question required} to Question +} + +dto Subject, Question, Choice, ExamAttempt, ExamAnswer with mapstruct +service Subject, Question, Choice, ExamAttempt, ExamAnswer with serviceClass +paginate Subject, Question, ExamAttempt with pagination diff --git a/src/main/java/com/example/questionbank/domain/Choice.java b/src/main/java/com/example/questionbank/domain/Choice.java new file mode 100644 index 0000000..ed931b0 --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/Choice.java @@ -0,0 +1,162 @@ +package com.example.questionbank.domain; + +import com.example.questionbank.domain.enumeration.OptionKey; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import jakarta.validation.constraints.*; +import java.io.Serial; +import java.io.Serializable; + +/** + * A Choice. + */ +@Entity +@Table(name = "choice") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class Choice implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "option_key", nullable = false) + private OptionKey optionKey; + + @NotNull + @Size(max = 500) + @Column(name = "content", length = 500, nullable = false) + private String content; + + @NotNull + @Min(value = 1) + @Max(value = 4) + @Column(name = "display_order", nullable = false) + private Integer displayOrder; + + @NotNull + @Column(name = "correct", nullable = false) + private Boolean correct; + + @ManyToOne(optional = false) + @NotNull + @JsonIgnoreProperties(value = { "choices", "subject" }, allowSetters = true) + private Question question; + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public Choice id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public OptionKey getOptionKey() { + return this.optionKey; + } + + public Choice optionKey(OptionKey optionKey) { + this.setOptionKey(optionKey); + return this; + } + + public void setOptionKey(OptionKey optionKey) { + this.optionKey = optionKey; + } + + public String getContent() { + return this.content; + } + + public Choice content(String content) { + this.setContent(content); + return this; + } + + public void setContent(String content) { + this.content = content; + } + + public Integer getDisplayOrder() { + return this.displayOrder; + } + + public Choice displayOrder(Integer displayOrder) { + this.setDisplayOrder(displayOrder); + return this; + } + + public void setDisplayOrder(Integer displayOrder) { + this.displayOrder = displayOrder; + } + + public Boolean getCorrect() { + return this.correct; + } + + public Choice correct(Boolean correct) { + this.setCorrect(correct); + return this; + } + + public void setCorrect(Boolean correct) { + this.correct = correct; + } + + public Question getQuestion() { + return this.question; + } + + public void setQuestion(Question question) { + this.question = question; + } + + public Choice question(Question question) { + this.setQuestion(question); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Choice)) { + return false; + } + return getId() != null && getId().equals(((Choice) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "Choice{" + + "id=" + getId() + + ", optionKey='" + getOptionKey() + "'" + + ", content='" + getContent() + "'" + + ", displayOrder=" + getDisplayOrder() + + ", correct='" + getCorrect() + "'" + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/domain/ExamAnswer.java b/src/main/java/com/example/questionbank/domain/ExamAnswer.java new file mode 100644 index 0000000..c33f28d --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/ExamAnswer.java @@ -0,0 +1,212 @@ +package com.example.questionbank.domain; + +import com.example.questionbank.domain.enumeration.OptionKey; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import jakarta.validation.constraints.*; +import java.io.Serial; +import java.io.Serializable; + +/** + * A ExamAnswer. + */ +@Entity +@Table(name = "exam_answer") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class ExamAnswer implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @NotNull + @Size(max = 2000) + @Column(name = "question_text_snapshot", length = 2000, nullable = false) + private String questionTextSnapshot; + + @Size(max = 2000) + @Column(name = "explanation_snapshot", length = 2000) + private String explanationSnapshot; + + @Enumerated(EnumType.STRING) + @Column(name = "selected_option") + private OptionKey selectedOption; + + @Size(max = 500) + @Column(name = "selected_content_snapshot", length = 500) + private String selectedContentSnapshot; + + @Column(name = "correct") + private Boolean correct; + + @Min(value = 0) + @Column(name = "awarded_points") + private Integer awardedPoints; + + @ManyToOne(optional = false) + @NotNull + @JsonIgnoreProperties(value = { "choices", "subject" }, allowSetters = true) + private Question question; + + @ManyToOne(optional = false) + @NotNull + @JsonIgnoreProperties(value = { "answers", "subject", "user" }, allowSetters = true) + private ExamAttempt attempt; + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public ExamAnswer id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public String getQuestionTextSnapshot() { + return this.questionTextSnapshot; + } + + public ExamAnswer questionTextSnapshot(String questionTextSnapshot) { + this.setQuestionTextSnapshot(questionTextSnapshot); + return this; + } + + public void setQuestionTextSnapshot(String questionTextSnapshot) { + this.questionTextSnapshot = questionTextSnapshot; + } + + public String getExplanationSnapshot() { + return this.explanationSnapshot; + } + + public ExamAnswer explanationSnapshot(String explanationSnapshot) { + this.setExplanationSnapshot(explanationSnapshot); + return this; + } + + public void setExplanationSnapshot(String explanationSnapshot) { + this.explanationSnapshot = explanationSnapshot; + } + + public OptionKey getSelectedOption() { + return this.selectedOption; + } + + public ExamAnswer selectedOption(OptionKey selectedOption) { + this.setSelectedOption(selectedOption); + return this; + } + + public void setSelectedOption(OptionKey selectedOption) { + this.selectedOption = selectedOption; + } + + public String getSelectedContentSnapshot() { + return this.selectedContentSnapshot; + } + + public ExamAnswer selectedContentSnapshot(String selectedContentSnapshot) { + this.setSelectedContentSnapshot(selectedContentSnapshot); + return this; + } + + public void setSelectedContentSnapshot(String selectedContentSnapshot) { + this.selectedContentSnapshot = selectedContentSnapshot; + } + + public Boolean getCorrect() { + return this.correct; + } + + public ExamAnswer correct(Boolean correct) { + this.setCorrect(correct); + return this; + } + + public void setCorrect(Boolean correct) { + this.correct = correct; + } + + public Integer getAwardedPoints() { + return this.awardedPoints; + } + + public ExamAnswer awardedPoints(Integer awardedPoints) { + this.setAwardedPoints(awardedPoints); + return this; + } + + public void setAwardedPoints(Integer awardedPoints) { + this.awardedPoints = awardedPoints; + } + + public Question getQuestion() { + return this.question; + } + + public void setQuestion(Question question) { + this.question = question; + } + + public ExamAnswer question(Question question) { + this.setQuestion(question); + return this; + } + + public ExamAttempt getAttempt() { + return this.attempt; + } + + public void setAttempt(ExamAttempt examAttempt) { + this.attempt = examAttempt; + } + + public ExamAnswer attempt(ExamAttempt examAttempt) { + this.setAttempt(examAttempt); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ExamAnswer)) { + return false; + } + return getId() != null && getId().equals(((ExamAnswer) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "ExamAnswer{" + + "id=" + getId() + + ", questionTextSnapshot='" + getQuestionTextSnapshot() + "'" + + ", explanationSnapshot='" + getExplanationSnapshot() + "'" + + ", selectedOption='" + getSelectedOption() + "'" + + ", selectedContentSnapshot='" + getSelectedContentSnapshot() + "'" + + ", correct='" + getCorrect() + "'" + + ", awardedPoints=" + getAwardedPoints() + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/domain/ExamAttempt.java b/src/main/java/com/example/questionbank/domain/ExamAttempt.java new file mode 100644 index 0000000..9b85ffe --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/ExamAttempt.java @@ -0,0 +1,212 @@ +package com.example.questionbank.domain; + +import com.example.questionbank.domain.enumeration.AttemptStatus; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import jakarta.validation.constraints.*; +import java.io.Serial; +import java.io.Serializable; +import java.time.Instant; +import java.util.HashSet; +import java.util.Set; + +/** + * A ExamAttempt. + */ +@Entity +@Table(name = "exam_attempt") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class ExamAttempt implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @NotNull + @Column(name = "started_at", nullable = false) + private Instant startedAt; + + @Column(name = "submitted_at") + private Instant submittedAt; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) + private AttemptStatus status; + + @Min(value = 0) + @Column(name = "score") + private Integer score; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "attempt") + @JsonIgnoreProperties(value = { "question", "attempt" }, allowSetters = true) + private Set answers = new HashSet<>(); + + @ManyToOne(optional = false) + @NotNull + private Subject subject; + + @ManyToOne(optional = false) + @NotNull + private User user; + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public ExamAttempt id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public Instant getStartedAt() { + return this.startedAt; + } + + public ExamAttempt startedAt(Instant startedAt) { + this.setStartedAt(startedAt); + return this; + } + + public void setStartedAt(Instant startedAt) { + this.startedAt = startedAt; + } + + public Instant getSubmittedAt() { + return this.submittedAt; + } + + public ExamAttempt submittedAt(Instant submittedAt) { + this.setSubmittedAt(submittedAt); + return this; + } + + public void setSubmittedAt(Instant submittedAt) { + this.submittedAt = submittedAt; + } + + public AttemptStatus getStatus() { + return this.status; + } + + public ExamAttempt status(AttemptStatus status) { + this.setStatus(status); + return this; + } + + public void setStatus(AttemptStatus status) { + this.status = status; + } + + public Integer getScore() { + return this.score; + } + + public ExamAttempt score(Integer score) { + this.setScore(score); + return this; + } + + public void setScore(Integer score) { + this.score = score; + } + + public Set getAnswers() { + return this.answers; + } + + public void setAnswers(Set examAnswers) { + if (this.answers != null) { + this.answers.forEach(i -> i.setAttempt(null)); + } + if (examAnswers != null) { + examAnswers.forEach(i -> i.setAttempt(this)); + } + this.answers = examAnswers; + } + + public ExamAttempt answers(Set examAnswers) { + this.setAnswers(examAnswers); + return this; + } + + public ExamAttempt addAnswer(ExamAnswer examAnswer) { + this.answers.add(examAnswer); + examAnswer.setAttempt(this); + return this; + } + + public ExamAttempt removeAnswer(ExamAnswer examAnswer) { + this.answers.remove(examAnswer); + examAnswer.setAttempt(null); + return this; + } + + public Subject getSubject() { + return this.subject; + } + + public void setSubject(Subject subject) { + this.subject = subject; + } + + public ExamAttempt subject(Subject subject) { + this.setSubject(subject); + return this; + } + + public User getUser() { + return this.user; + } + + public void setUser(User user) { + this.user = user; + } + + public ExamAttempt user(User user) { + this.setUser(user); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ExamAttempt)) { + return false; + } + return getId() != null && getId().equals(((ExamAttempt) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "ExamAttempt{" + + "id=" + getId() + + ", startedAt='" + getStartedAt() + "'" + + ", submittedAt='" + getSubmittedAt() + "'" + + ", status='" + getStatus() + "'" + + ", score=" + getScore() + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/domain/Question.java b/src/main/java/com/example/questionbank/domain/Question.java new file mode 100644 index 0000000..4e6457a --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/Question.java @@ -0,0 +1,176 @@ +package com.example.questionbank.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.*; +import jakarta.validation.constraints.*; +import java.io.Serial; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +/** + * A Question. + */ +@Entity +@Table(name = "question") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class Question implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @NotNull + @Size(min = 5, max = 2000) + @Column(name = "prompt", length = 2000, nullable = false) + private String prompt; + + @Size(max = 2000) + @Column(name = "explanation", length = 2000) + private String explanation; + + @NotNull + @Column(name = "active", nullable = false) + private Boolean active; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "question") + @JsonIgnoreProperties(value = { "question" }, allowSetters = true) + private Set choices = new HashSet<>(); + + @ManyToOne(optional = false) + @NotNull + private Subject subject; + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public Question id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPrompt() { + return this.prompt; + } + + public Question prompt(String prompt) { + this.setPrompt(prompt); + return this; + } + + public void setPrompt(String prompt) { + this.prompt = prompt; + } + + public String getExplanation() { + return this.explanation; + } + + public Question explanation(String explanation) { + this.setExplanation(explanation); + return this; + } + + public void setExplanation(String explanation) { + this.explanation = explanation; + } + + public Boolean getActive() { + return this.active; + } + + public Question active(Boolean active) { + this.setActive(active); + return this; + } + + public void setActive(Boolean active) { + this.active = active; + } + + public Set getChoices() { + return this.choices; + } + + public void setChoices(Set choices) { + if (this.choices != null) { + this.choices.forEach(i -> i.setQuestion(null)); + } + if (choices != null) { + choices.forEach(i -> i.setQuestion(this)); + } + this.choices = choices; + } + + public Question choices(Set choices) { + this.setChoices(choices); + return this; + } + + public Question addChoice(Choice choice) { + this.choices.add(choice); + choice.setQuestion(this); + return this; + } + + public Question removeChoice(Choice choice) { + this.choices.remove(choice); + choice.setQuestion(null); + return this; + } + + public Subject getSubject() { + return this.subject; + } + + public void setSubject(Subject subject) { + this.subject = subject; + } + + public Question subject(Subject subject) { + this.setSubject(subject); + return this; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Question)) { + return false; + } + return getId() != null && getId().equals(((Question) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "Question{" + + "id=" + getId() + + ", prompt='" + getPrompt() + "'" + + ", explanation='" + getExplanation() + "'" + + ", active='" + getActive() + "'" + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/domain/Subject.java b/src/main/java/com/example/questionbank/domain/Subject.java new file mode 100644 index 0000000..7e71757 --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/Subject.java @@ -0,0 +1,121 @@ +package com.example.questionbank.domain; + +import jakarta.persistence.*; +import jakarta.validation.constraints.*; +import java.io.Serial; +import java.io.Serializable; + +/** + * A Subject. + */ +@Entity +@Table(name = "subject") +@SuppressWarnings("common-java:DuplicatedBlocks") +public class Subject implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") + @SequenceGenerator(name = "sequenceGenerator") + @Column(name = "id") + private Long id; + + @NotNull + @Size(min = 2, max = 100) + @Column(name = "name", length = 100, nullable = false) + private String name; + + @Size(max = 1000) + @Column(name = "description", length = 1000) + private String description; + + @NotNull + @Column(name = "active", nullable = false) + private Boolean active; + + // jhipster-needle-entity-add-field - JHipster will add fields here + + public Long getId() { + return this.id; + } + + public Subject id(Long id) { + this.setId(id); + return this; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public Subject name(String name) { + this.setName(name); + return this; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return this.description; + } + + public Subject description(String description) { + this.setDescription(description); + return this; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getActive() { + return this.active; + } + + public Subject active(Boolean active) { + this.setActive(active); + return this; + } + + public void setActive(Boolean active) { + this.active = active; + } + + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Subject)) { + return false; + } + return getId() != null && getId().equals(((Subject) o).getId()); + } + + @Override + public int hashCode() { + // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ + return getClass().hashCode(); + } + + // prettier-ignore + @Override + public String toString() { + return "Subject{" + + "id=" + getId() + + ", name='" + getName() + "'" + + ", description='" + getDescription() + "'" + + ", active='" + getActive() + "'" + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/domain/enumeration/AttemptStatus.java b/src/main/java/com/example/questionbank/domain/enumeration/AttemptStatus.java new file mode 100644 index 0000000..d02932f --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/enumeration/AttemptStatus.java @@ -0,0 +1,9 @@ +package com.example.questionbank.domain.enumeration; + +/** + * The AttemptStatus enumeration. + */ +public enum AttemptStatus { + IN_PROGRESS, + SUBMITTED, +} diff --git a/src/main/java/com/example/questionbank/domain/enumeration/OptionKey.java b/src/main/java/com/example/questionbank/domain/enumeration/OptionKey.java new file mode 100644 index 0000000..8294803 --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/enumeration/OptionKey.java @@ -0,0 +1,11 @@ +package com.example.questionbank.domain.enumeration; + +/** + * The OptionKey enumeration. + */ +public enum OptionKey { + A, + B, + C, + D, +} diff --git a/src/main/java/com/example/questionbank/domain/enumeration/package-info.java b/src/main/java/com/example/questionbank/domain/enumeration/package-info.java new file mode 100644 index 0000000..b1cb9ca --- /dev/null +++ b/src/main/java/com/example/questionbank/domain/enumeration/package-info.java @@ -0,0 +1,4 @@ +/** + * This package file was generated by JHipster + */ +package com.example.questionbank.domain.enumeration; diff --git a/src/main/java/com/example/questionbank/repository/ChoiceRepository.java b/src/main/java/com/example/questionbank/repository/ChoiceRepository.java new file mode 100644 index 0000000..8995fdf --- /dev/null +++ b/src/main/java/com/example/questionbank/repository/ChoiceRepository.java @@ -0,0 +1,12 @@ +package com.example.questionbank.repository; + +import com.example.questionbank.domain.Choice; +import org.springframework.data.jpa.repository.*; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the Choice entity. + */ +@SuppressWarnings("unused") +@Repository +public interface ChoiceRepository extends JpaRepository {} diff --git a/src/main/java/com/example/questionbank/repository/ExamAnswerRepository.java b/src/main/java/com/example/questionbank/repository/ExamAnswerRepository.java new file mode 100644 index 0000000..13749e9 --- /dev/null +++ b/src/main/java/com/example/questionbank/repository/ExamAnswerRepository.java @@ -0,0 +1,12 @@ +package com.example.questionbank.repository; + +import com.example.questionbank.domain.ExamAnswer; +import org.springframework.data.jpa.repository.*; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the ExamAnswer entity. + */ +@SuppressWarnings("unused") +@Repository +public interface ExamAnswerRepository extends JpaRepository {} diff --git a/src/main/java/com/example/questionbank/repository/ExamAttemptRepository.java b/src/main/java/com/example/questionbank/repository/ExamAttemptRepository.java new file mode 100644 index 0000000..616b945 --- /dev/null +++ b/src/main/java/com/example/questionbank/repository/ExamAttemptRepository.java @@ -0,0 +1,45 @@ +package com.example.questionbank.repository; + +import com.example.questionbank.domain.ExamAttempt; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.*; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the ExamAttempt entity. + */ +@Repository +public interface ExamAttemptRepository extends JpaRepository { + @Query("select examAttempt from ExamAttempt examAttempt where examAttempt.user.login = ?#{authentication.name}") + List findByUserIsCurrentUser(); + + default Optional findOneWithEagerRelationships(Long id) { + return this.findOneWithToOneRelationships(id); + } + + default List findAllWithEagerRelationships() { + return this.findAllWithToOneRelationships(); + } + + default Page findAllWithEagerRelationships(Pageable pageable) { + return this.findAllWithToOneRelationships(pageable); + } + + @Query( + value = "select examAttempt from ExamAttempt examAttempt left join fetch examAttempt.subject left join fetch examAttempt.user", + countQuery = "select count(examAttempt) from ExamAttempt examAttempt" + ) + Page findAllWithToOneRelationships(Pageable pageable); + + @Query("select examAttempt from ExamAttempt examAttempt left join fetch examAttempt.subject left join fetch examAttempt.user") + List findAllWithToOneRelationships(); + + @Query( + "select examAttempt from ExamAttempt examAttempt left join fetch examAttempt.subject left join fetch examAttempt.user where examAttempt.id =:id" + ) + Optional findOneWithToOneRelationships(@Param("id") Long id); +} diff --git a/src/main/java/com/example/questionbank/repository/QuestionRepository.java b/src/main/java/com/example/questionbank/repository/QuestionRepository.java new file mode 100644 index 0000000..b6c10bb --- /dev/null +++ b/src/main/java/com/example/questionbank/repository/QuestionRepository.java @@ -0,0 +1,40 @@ +package com.example.questionbank.repository; + +import com.example.questionbank.domain.Question; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.*; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the Question entity. + */ +@Repository +public interface QuestionRepository extends JpaRepository { + default Optional findOneWithEagerRelationships(Long id) { + return this.findOneWithToOneRelationships(id); + } + + default List findAllWithEagerRelationships() { + return this.findAllWithToOneRelationships(); + } + + default Page findAllWithEagerRelationships(Pageable pageable) { + return this.findAllWithToOneRelationships(pageable); + } + + @Query( + value = "select question from Question question left join fetch question.subject", + countQuery = "select count(question) from Question question" + ) + Page findAllWithToOneRelationships(Pageable pageable); + + @Query("select question from Question question left join fetch question.subject") + List findAllWithToOneRelationships(); + + @Query("select question from Question question left join fetch question.subject where question.id =:id") + Optional findOneWithToOneRelationships(@Param("id") Long id); +} diff --git a/src/main/java/com/example/questionbank/repository/SubjectRepository.java b/src/main/java/com/example/questionbank/repository/SubjectRepository.java new file mode 100644 index 0000000..b16880d --- /dev/null +++ b/src/main/java/com/example/questionbank/repository/SubjectRepository.java @@ -0,0 +1,12 @@ +package com.example.questionbank.repository; + +import com.example.questionbank.domain.Subject; +import org.springframework.data.jpa.repository.*; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the Subject entity. + */ +@SuppressWarnings("unused") +@Repository +public interface SubjectRepository extends JpaRepository {} diff --git a/src/main/java/com/example/questionbank/service/ChoiceService.java b/src/main/java/com/example/questionbank/service/ChoiceService.java new file mode 100644 index 0000000..540702d --- /dev/null +++ b/src/main/java/com/example/questionbank/service/ChoiceService.java @@ -0,0 +1,112 @@ +package com.example.questionbank.service; + +import com.example.questionbank.domain.Choice; +import com.example.questionbank.repository.ChoiceRepository; +import com.example.questionbank.service.dto.ChoiceDTO; +import com.example.questionbank.service.mapper.ChoiceMapper; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Service Implementation for managing {@link com.example.questionbank.domain.Choice}. + */ +@Service +@Transactional +public class ChoiceService { + + private static final Logger LOG = LoggerFactory.getLogger(ChoiceService.class); + + private final ChoiceRepository choiceRepository; + + private final ChoiceMapper choiceMapper; + + public ChoiceService(ChoiceRepository choiceRepository, ChoiceMapper choiceMapper) { + this.choiceRepository = choiceRepository; + this.choiceMapper = choiceMapper; + } + + /** + * Save a choice. + * + * @param choiceDTO the entity to save. + * @return the persisted entity. + */ + public ChoiceDTO save(ChoiceDTO choiceDTO) { + LOG.debug("Request to save Choice : {}", choiceDTO); + Choice choice = choiceMapper.toEntity(choiceDTO); + choice = choiceRepository.save(choice); + return choiceMapper.toDto(choice); + } + + /** + * Update a choice. + * + * @param choiceDTO the entity to save. + * @return the persisted entity. + */ + public ChoiceDTO update(ChoiceDTO choiceDTO) { + LOG.debug("Request to update Choice : {}", choiceDTO); + Choice choice = choiceMapper.toEntity(choiceDTO); + choice = choiceRepository.save(choice); + return choiceMapper.toDto(choice); + } + + /** + * Partially update a choice. + * + * @param choiceDTO the entity to update partially. + * @return the persisted entity. + */ + public Optional partialUpdate(ChoiceDTO choiceDTO) { + LOG.debug("Request to partially update Choice : {}", choiceDTO); + + return choiceRepository + .findById(choiceDTO.getId()) + .map(existingChoice -> { + choiceMapper.partialUpdate(existingChoice, choiceDTO); + + return existingChoice; + }) + .map(choiceRepository::save) + .map(choiceMapper::toDto); + } + + /** + * Get all the choices. + * + * @return the list of entities. + */ + @Transactional(readOnly = true) + public List findAll() { + LOG.debug("Request to get all Choices"); + return choiceRepository.findAll().stream().map(choiceMapper::toDto).collect(Collectors.toCollection(LinkedList::new)); + } + + /** + * Get one choice by id. + * + * @param id the id of the entity. + * @return the entity. + */ + @Transactional(readOnly = true) + public Optional findOne(Long id) { + LOG.debug("Request to get Choice : {}", id); + return choiceRepository.findById(id).map(choiceMapper::toDto); + } + + /** + * Delete the choice by id. + * + * @param id the id of the entity. + */ + public void delete(Long id) { + LOG.debug("Request to delete Choice : {}", id); + choiceRepository.deleteById(id); + } +} diff --git a/src/main/java/com/example/questionbank/service/ExamAnswerService.java b/src/main/java/com/example/questionbank/service/ExamAnswerService.java new file mode 100644 index 0000000..949f0a7 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/ExamAnswerService.java @@ -0,0 +1,112 @@ +package com.example.questionbank.service; + +import com.example.questionbank.domain.ExamAnswer; +import com.example.questionbank.repository.ExamAnswerRepository; +import com.example.questionbank.service.dto.ExamAnswerDTO; +import com.example.questionbank.service.mapper.ExamAnswerMapper; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Service Implementation for managing {@link com.example.questionbank.domain.ExamAnswer}. + */ +@Service +@Transactional +public class ExamAnswerService { + + private static final Logger LOG = LoggerFactory.getLogger(ExamAnswerService.class); + + private final ExamAnswerRepository examAnswerRepository; + + private final ExamAnswerMapper examAnswerMapper; + + public ExamAnswerService(ExamAnswerRepository examAnswerRepository, ExamAnswerMapper examAnswerMapper) { + this.examAnswerRepository = examAnswerRepository; + this.examAnswerMapper = examAnswerMapper; + } + + /** + * Save a examAnswer. + * + * @param examAnswerDTO the entity to save. + * @return the persisted entity. + */ + public ExamAnswerDTO save(ExamAnswerDTO examAnswerDTO) { + LOG.debug("Request to save ExamAnswer : {}", examAnswerDTO); + ExamAnswer examAnswer = examAnswerMapper.toEntity(examAnswerDTO); + examAnswer = examAnswerRepository.save(examAnswer); + return examAnswerMapper.toDto(examAnswer); + } + + /** + * Update a examAnswer. + * + * @param examAnswerDTO the entity to save. + * @return the persisted entity. + */ + public ExamAnswerDTO update(ExamAnswerDTO examAnswerDTO) { + LOG.debug("Request to update ExamAnswer : {}", examAnswerDTO); + ExamAnswer examAnswer = examAnswerMapper.toEntity(examAnswerDTO); + examAnswer = examAnswerRepository.save(examAnswer); + return examAnswerMapper.toDto(examAnswer); + } + + /** + * Partially update a examAnswer. + * + * @param examAnswerDTO the entity to update partially. + * @return the persisted entity. + */ + public Optional partialUpdate(ExamAnswerDTO examAnswerDTO) { + LOG.debug("Request to partially update ExamAnswer : {}", examAnswerDTO); + + return examAnswerRepository + .findById(examAnswerDTO.getId()) + .map(existingExamAnswer -> { + examAnswerMapper.partialUpdate(existingExamAnswer, examAnswerDTO); + + return existingExamAnswer; + }) + .map(examAnswerRepository::save) + .map(examAnswerMapper::toDto); + } + + /** + * Get all the examAnswers. + * + * @return the list of entities. + */ + @Transactional(readOnly = true) + public List findAll() { + LOG.debug("Request to get all ExamAnswers"); + return examAnswerRepository.findAll().stream().map(examAnswerMapper::toDto).collect(Collectors.toCollection(LinkedList::new)); + } + + /** + * Get one examAnswer by id. + * + * @param id the id of the entity. + * @return the entity. + */ + @Transactional(readOnly = true) + public Optional findOne(Long id) { + LOG.debug("Request to get ExamAnswer : {}", id); + return examAnswerRepository.findById(id).map(examAnswerMapper::toDto); + } + + /** + * Delete the examAnswer by id. + * + * @param id the id of the entity. + */ + public void delete(Long id) { + LOG.debug("Request to delete ExamAnswer : {}", id); + examAnswerRepository.deleteById(id); + } +} diff --git a/src/main/java/com/example/questionbank/service/ExamAttemptService.java b/src/main/java/com/example/questionbank/service/ExamAttemptService.java new file mode 100644 index 0000000..030d43e --- /dev/null +++ b/src/main/java/com/example/questionbank/service/ExamAttemptService.java @@ -0,0 +1,121 @@ +package com.example.questionbank.service; + +import com.example.questionbank.domain.ExamAttempt; +import com.example.questionbank.repository.ExamAttemptRepository; +import com.example.questionbank.service.dto.ExamAttemptDTO; +import com.example.questionbank.service.mapper.ExamAttemptMapper; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Service Implementation for managing {@link com.example.questionbank.domain.ExamAttempt}. + */ +@Service +@Transactional +public class ExamAttemptService { + + private static final Logger LOG = LoggerFactory.getLogger(ExamAttemptService.class); + + private final ExamAttemptRepository examAttemptRepository; + + private final ExamAttemptMapper examAttemptMapper; + + public ExamAttemptService(ExamAttemptRepository examAttemptRepository, ExamAttemptMapper examAttemptMapper) { + this.examAttemptRepository = examAttemptRepository; + this.examAttemptMapper = examAttemptMapper; + } + + /** + * Save a examAttempt. + * + * @param examAttemptDTO the entity to save. + * @return the persisted entity. + */ + public ExamAttemptDTO save(ExamAttemptDTO examAttemptDTO) { + LOG.debug("Request to save ExamAttempt : {}", examAttemptDTO); + ExamAttempt examAttempt = examAttemptMapper.toEntity(examAttemptDTO); + examAttempt = examAttemptRepository.save(examAttempt); + return examAttemptMapper.toDto(examAttempt); + } + + /** + * Update a examAttempt. + * + * @param examAttemptDTO the entity to save. + * @return the persisted entity. + */ + public ExamAttemptDTO update(ExamAttemptDTO examAttemptDTO) { + LOG.debug("Request to update ExamAttempt : {}", examAttemptDTO); + ExamAttempt examAttempt = examAttemptMapper.toEntity(examAttemptDTO); + examAttempt = examAttemptRepository.save(examAttempt); + return examAttemptMapper.toDto(examAttempt); + } + + /** + * Partially update a examAttempt. + * + * @param examAttemptDTO the entity to update partially. + * @return the persisted entity. + */ + public Optional partialUpdate(ExamAttemptDTO examAttemptDTO) { + LOG.debug("Request to partially update ExamAttempt : {}", examAttemptDTO); + + return examAttemptRepository + .findById(examAttemptDTO.getId()) + .map(existingExamAttempt -> { + examAttemptMapper.partialUpdate(existingExamAttempt, examAttemptDTO); + + return existingExamAttempt; + }) + .map(examAttemptRepository::save) + .map(examAttemptMapper::toDto); + } + + /** + * Get all the examAttempts. + * + * @param pageable the pagination information. + * @return the list of entities. + */ + @Transactional(readOnly = true) + public Page findAll(Pageable pageable) { + LOG.debug("Request to get all ExamAttempts"); + return examAttemptRepository.findAll(pageable).map(examAttemptMapper::toDto); + } + + /** + * Get all the examAttempts with eager load of many-to-many relationships. + * + * @return the list of entities. + */ + public Page findAllWithEagerRelationships(Pageable pageable) { + return examAttemptRepository.findAllWithEagerRelationships(pageable).map(examAttemptMapper::toDto); + } + + /** + * Get one examAttempt by id. + * + * @param id the id of the entity. + * @return the entity. + */ + @Transactional(readOnly = true) + public Optional findOne(Long id) { + LOG.debug("Request to get ExamAttempt : {}", id); + return examAttemptRepository.findOneWithEagerRelationships(id).map(examAttemptMapper::toDto); + } + + /** + * Delete the examAttempt by id. + * + * @param id the id of the entity. + */ + public void delete(Long id) { + LOG.debug("Request to delete ExamAttempt : {}", id); + examAttemptRepository.deleteById(id); + } +} diff --git a/src/main/java/com/example/questionbank/service/QuestionService.java b/src/main/java/com/example/questionbank/service/QuestionService.java new file mode 100644 index 0000000..7f3e4e9 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/QuestionService.java @@ -0,0 +1,121 @@ +package com.example.questionbank.service; + +import com.example.questionbank.domain.Question; +import com.example.questionbank.repository.QuestionRepository; +import com.example.questionbank.service.dto.QuestionDTO; +import com.example.questionbank.service.mapper.QuestionMapper; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Service Implementation for managing {@link com.example.questionbank.domain.Question}. + */ +@Service +@Transactional +public class QuestionService { + + private static final Logger LOG = LoggerFactory.getLogger(QuestionService.class); + + private final QuestionRepository questionRepository; + + private final QuestionMapper questionMapper; + + public QuestionService(QuestionRepository questionRepository, QuestionMapper questionMapper) { + this.questionRepository = questionRepository; + this.questionMapper = questionMapper; + } + + /** + * Save a question. + * + * @param questionDTO the entity to save. + * @return the persisted entity. + */ + public QuestionDTO save(QuestionDTO questionDTO) { + LOG.debug("Request to save Question : {}", questionDTO); + Question question = questionMapper.toEntity(questionDTO); + question = questionRepository.save(question); + return questionMapper.toDto(question); + } + + /** + * Update a question. + * + * @param questionDTO the entity to save. + * @return the persisted entity. + */ + public QuestionDTO update(QuestionDTO questionDTO) { + LOG.debug("Request to update Question : {}", questionDTO); + Question question = questionMapper.toEntity(questionDTO); + question = questionRepository.save(question); + return questionMapper.toDto(question); + } + + /** + * Partially update a question. + * + * @param questionDTO the entity to update partially. + * @return the persisted entity. + */ + public Optional partialUpdate(QuestionDTO questionDTO) { + LOG.debug("Request to partially update Question : {}", questionDTO); + + return questionRepository + .findById(questionDTO.getId()) + .map(existingQuestion -> { + questionMapper.partialUpdate(existingQuestion, questionDTO); + + return existingQuestion; + }) + .map(questionRepository::save) + .map(questionMapper::toDto); + } + + /** + * Get all the questions. + * + * @param pageable the pagination information. + * @return the list of entities. + */ + @Transactional(readOnly = true) + public Page findAll(Pageable pageable) { + LOG.debug("Request to get all Questions"); + return questionRepository.findAll(pageable).map(questionMapper::toDto); + } + + /** + * Get all the questions with eager load of many-to-many relationships. + * + * @return the list of entities. + */ + public Page findAllWithEagerRelationships(Pageable pageable) { + return questionRepository.findAllWithEagerRelationships(pageable).map(questionMapper::toDto); + } + + /** + * Get one question by id. + * + * @param id the id of the entity. + * @return the entity. + */ + @Transactional(readOnly = true) + public Optional findOne(Long id) { + LOG.debug("Request to get Question : {}", id); + return questionRepository.findOneWithEagerRelationships(id).map(questionMapper::toDto); + } + + /** + * Delete the question by id. + * + * @param id the id of the entity. + */ + public void delete(Long id) { + LOG.debug("Request to delete Question : {}", id); + questionRepository.deleteById(id); + } +} diff --git a/src/main/java/com/example/questionbank/service/SubjectService.java b/src/main/java/com/example/questionbank/service/SubjectService.java new file mode 100644 index 0000000..50c1917 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/SubjectService.java @@ -0,0 +1,112 @@ +package com.example.questionbank.service; + +import com.example.questionbank.domain.Subject; +import com.example.questionbank.repository.SubjectRepository; +import com.example.questionbank.service.dto.SubjectDTO; +import com.example.questionbank.service.mapper.SubjectMapper; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Service Implementation for managing {@link com.example.questionbank.domain.Subject}. + */ +@Service +@Transactional +public class SubjectService { + + private static final Logger LOG = LoggerFactory.getLogger(SubjectService.class); + + private final SubjectRepository subjectRepository; + + private final SubjectMapper subjectMapper; + + public SubjectService(SubjectRepository subjectRepository, SubjectMapper subjectMapper) { + this.subjectRepository = subjectRepository; + this.subjectMapper = subjectMapper; + } + + /** + * Save a subject. + * + * @param subjectDTO the entity to save. + * @return the persisted entity. + */ + public SubjectDTO save(SubjectDTO subjectDTO) { + LOG.debug("Request to save Subject : {}", subjectDTO); + Subject subject = subjectMapper.toEntity(subjectDTO); + subject = subjectRepository.save(subject); + return subjectMapper.toDto(subject); + } + + /** + * Update a subject. + * + * @param subjectDTO the entity to save. + * @return the persisted entity. + */ + public SubjectDTO update(SubjectDTO subjectDTO) { + LOG.debug("Request to update Subject : {}", subjectDTO); + Subject subject = subjectMapper.toEntity(subjectDTO); + subject = subjectRepository.save(subject); + return subjectMapper.toDto(subject); + } + + /** + * Partially update a subject. + * + * @param subjectDTO the entity to update partially. + * @return the persisted entity. + */ + public Optional partialUpdate(SubjectDTO subjectDTO) { + LOG.debug("Request to partially update Subject : {}", subjectDTO); + + return subjectRepository + .findById(subjectDTO.getId()) + .map(existingSubject -> { + subjectMapper.partialUpdate(existingSubject, subjectDTO); + + return existingSubject; + }) + .map(subjectRepository::save) + .map(subjectMapper::toDto); + } + + /** + * Get all the subjects. + * + * @param pageable the pagination information. + * @return the list of entities. + */ + @Transactional(readOnly = true) + public Page findAll(Pageable pageable) { + LOG.debug("Request to get all Subjects"); + return subjectRepository.findAll(pageable).map(subjectMapper::toDto); + } + + /** + * Get one subject by id. + * + * @param id the id of the entity. + * @return the entity. + */ + @Transactional(readOnly = true) + public Optional findOne(Long id) { + LOG.debug("Request to get Subject : {}", id); + return subjectRepository.findById(id).map(subjectMapper::toDto); + } + + /** + * Delete the subject by id. + * + * @param id the id of the entity. + */ + public void delete(Long id) { + LOG.debug("Request to delete Subject : {}", id); + subjectRepository.deleteById(id); + } +} diff --git a/src/main/java/com/example/questionbank/service/dto/ChoiceDTO.java b/src/main/java/com/example/questionbank/service/dto/ChoiceDTO.java new file mode 100644 index 0000000..5cadcf2 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/dto/ChoiceDTO.java @@ -0,0 +1,115 @@ +package com.example.questionbank.service.dto; + +import com.example.questionbank.domain.enumeration.OptionKey; +import jakarta.validation.constraints.*; +import java.io.Serializable; +import java.util.Objects; + +/** + * A DTO for the {@link com.example.questionbank.domain.Choice} entity. + */ +@SuppressWarnings("common-java:DuplicatedBlocks") +public class ChoiceDTO implements Serializable { + + private Long id; + + @NotNull + private OptionKey optionKey; + + @NotNull + @Size(max = 500) + private String content; + + @NotNull + @Min(value = 1) + @Max(value = 4) + private Integer displayOrder; + + @NotNull + private Boolean correct; + + @NotNull + private QuestionDTO question; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public OptionKey getOptionKey() { + return optionKey; + } + + public void setOptionKey(OptionKey optionKey) { + this.optionKey = optionKey; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Integer getDisplayOrder() { + return displayOrder; + } + + public void setDisplayOrder(Integer displayOrder) { + this.displayOrder = displayOrder; + } + + public Boolean getCorrect() { + return correct; + } + + public void setCorrect(Boolean correct) { + this.correct = correct; + } + + public QuestionDTO getQuestion() { + return question; + } + + public void setQuestion(QuestionDTO question) { + this.question = question; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ChoiceDTO)) { + return false; + } + + ChoiceDTO choiceDTO = (ChoiceDTO) o; + if (this.id == null) { + return false; + } + return Objects.equals(this.id, choiceDTO.id); + } + + @Override + public int hashCode() { + return Objects.hash(this.id); + } + + // prettier-ignore + @Override + public String toString() { + return "ChoiceDTO{" + + "id=" + getId() + + ", optionKey='" + getOptionKey() + "'" + + ", content='" + getContent() + "'" + + ", displayOrder=" + getDisplayOrder() + + ", correct='" + getCorrect() + "'" + + ", question=" + getQuestion() + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/service/dto/ExamAnswerDTO.java b/src/main/java/com/example/questionbank/service/dto/ExamAnswerDTO.java new file mode 100644 index 0000000..74d7db9 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/dto/ExamAnswerDTO.java @@ -0,0 +1,147 @@ +package com.example.questionbank.service.dto; + +import com.example.questionbank.domain.enumeration.OptionKey; +import jakarta.validation.constraints.*; +import java.io.Serializable; +import java.util.Objects; + +/** + * A DTO for the {@link com.example.questionbank.domain.ExamAnswer} entity. + */ +@SuppressWarnings("common-java:DuplicatedBlocks") +public class ExamAnswerDTO implements Serializable { + + private Long id; + + @NotNull + @Size(max = 2000) + private String questionTextSnapshot; + + @Size(max = 2000) + private String explanationSnapshot; + + private OptionKey selectedOption; + + @Size(max = 500) + private String selectedContentSnapshot; + + private Boolean correct; + + @Min(value = 0) + private Integer awardedPoints; + + @NotNull + private QuestionDTO question; + + @NotNull + private ExamAttemptDTO attempt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getQuestionTextSnapshot() { + return questionTextSnapshot; + } + + public void setQuestionTextSnapshot(String questionTextSnapshot) { + this.questionTextSnapshot = questionTextSnapshot; + } + + public String getExplanationSnapshot() { + return explanationSnapshot; + } + + public void setExplanationSnapshot(String explanationSnapshot) { + this.explanationSnapshot = explanationSnapshot; + } + + public OptionKey getSelectedOption() { + return selectedOption; + } + + public void setSelectedOption(OptionKey selectedOption) { + this.selectedOption = selectedOption; + } + + public String getSelectedContentSnapshot() { + return selectedContentSnapshot; + } + + public void setSelectedContentSnapshot(String selectedContentSnapshot) { + this.selectedContentSnapshot = selectedContentSnapshot; + } + + public Boolean getCorrect() { + return correct; + } + + public void setCorrect(Boolean correct) { + this.correct = correct; + } + + public Integer getAwardedPoints() { + return awardedPoints; + } + + public void setAwardedPoints(Integer awardedPoints) { + this.awardedPoints = awardedPoints; + } + + public QuestionDTO getQuestion() { + return question; + } + + public void setQuestion(QuestionDTO question) { + this.question = question; + } + + public ExamAttemptDTO getAttempt() { + return attempt; + } + + public void setAttempt(ExamAttemptDTO attempt) { + this.attempt = attempt; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ExamAnswerDTO)) { + return false; + } + + ExamAnswerDTO examAnswerDTO = (ExamAnswerDTO) o; + if (this.id == null) { + return false; + } + return Objects.equals(this.id, examAnswerDTO.id); + } + + @Override + public int hashCode() { + return Objects.hash(this.id); + } + + // prettier-ignore + @Override + public String toString() { + return "ExamAnswerDTO{" + + "id=" + getId() + + ", questionTextSnapshot='" + getQuestionTextSnapshot() + "'" + + ", explanationSnapshot='" + getExplanationSnapshot() + "'" + + ", selectedOption='" + getSelectedOption() + "'" + + ", selectedContentSnapshot='" + getSelectedContentSnapshot() + "'" + + ", correct='" + getCorrect() + "'" + + ", awardedPoints=" + getAwardedPoints() + + ", question=" + getQuestion() + + ", attempt=" + getAttempt() + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/service/dto/ExamAttemptDTO.java b/src/main/java/com/example/questionbank/service/dto/ExamAttemptDTO.java new file mode 100644 index 0000000..77c704d --- /dev/null +++ b/src/main/java/com/example/questionbank/service/dto/ExamAttemptDTO.java @@ -0,0 +1,124 @@ +package com.example.questionbank.service.dto; + +import com.example.questionbank.domain.enumeration.AttemptStatus; +import jakarta.validation.constraints.*; +import java.io.Serializable; +import java.time.Instant; +import java.util.Objects; + +/** + * A DTO for the {@link com.example.questionbank.domain.ExamAttempt} entity. + */ +@SuppressWarnings("common-java:DuplicatedBlocks") +public class ExamAttemptDTO implements Serializable { + + private Long id; + + @NotNull + private Instant startedAt; + + private Instant submittedAt; + + @NotNull + private AttemptStatus status; + + @Min(value = 0) + private Integer score; + + @NotNull + private SubjectDTO subject; + + @NotNull + private UserDTO user; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Instant getStartedAt() { + return startedAt; + } + + public void setStartedAt(Instant startedAt) { + this.startedAt = startedAt; + } + + public Instant getSubmittedAt() { + return submittedAt; + } + + public void setSubmittedAt(Instant submittedAt) { + this.submittedAt = submittedAt; + } + + public AttemptStatus getStatus() { + return status; + } + + public void setStatus(AttemptStatus status) { + this.status = status; + } + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + public SubjectDTO getSubject() { + return subject; + } + + public void setSubject(SubjectDTO subject) { + this.subject = subject; + } + + public UserDTO getUser() { + return user; + } + + public void setUser(UserDTO user) { + this.user = user; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ExamAttemptDTO)) { + return false; + } + + ExamAttemptDTO examAttemptDTO = (ExamAttemptDTO) o; + if (this.id == null) { + return false; + } + return Objects.equals(this.id, examAttemptDTO.id); + } + + @Override + public int hashCode() { + return Objects.hash(this.id); + } + + // prettier-ignore + @Override + public String toString() { + return "ExamAttemptDTO{" + + "id=" + getId() + + ", startedAt='" + getStartedAt() + "'" + + ", submittedAt='" + getSubmittedAt() + "'" + + ", status='" + getStatus() + "'" + + ", score=" + getScore() + + ", subject=" + getSubject() + + ", user=" + getUser() + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/service/dto/QuestionDTO.java b/src/main/java/com/example/questionbank/service/dto/QuestionDTO.java new file mode 100644 index 0000000..b3f620d --- /dev/null +++ b/src/main/java/com/example/questionbank/service/dto/QuestionDTO.java @@ -0,0 +1,100 @@ +package com.example.questionbank.service.dto; + +import jakarta.validation.constraints.*; +import java.io.Serializable; +import java.util.Objects; + +/** + * A DTO for the {@link com.example.questionbank.domain.Question} entity. + */ +@SuppressWarnings("common-java:DuplicatedBlocks") +public class QuestionDTO implements Serializable { + + private Long id; + + @NotNull + @Size(min = 5, max = 2000) + private String prompt; + + @Size(max = 2000) + private String explanation; + + @NotNull + private Boolean active; + + @NotNull + private SubjectDTO subject; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPrompt() { + return prompt; + } + + public void setPrompt(String prompt) { + this.prompt = prompt; + } + + public String getExplanation() { + return explanation; + } + + public void setExplanation(String explanation) { + this.explanation = explanation; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + + public SubjectDTO getSubject() { + return subject; + } + + public void setSubject(SubjectDTO subject) { + this.subject = subject; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof QuestionDTO)) { + return false; + } + + QuestionDTO questionDTO = (QuestionDTO) o; + if (this.id == null) { + return false; + } + return Objects.equals(this.id, questionDTO.id); + } + + @Override + public int hashCode() { + return Objects.hash(this.id); + } + + // prettier-ignore + @Override + public String toString() { + return "QuestionDTO{" + + "id=" + getId() + + ", prompt='" + getPrompt() + "'" + + ", explanation='" + getExplanation() + "'" + + ", active='" + getActive() + "'" + + ", subject=" + getSubject() + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/service/dto/SubjectDTO.java b/src/main/java/com/example/questionbank/service/dto/SubjectDTO.java new file mode 100644 index 0000000..a844380 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/dto/SubjectDTO.java @@ -0,0 +1,88 @@ +package com.example.questionbank.service.dto; + +import jakarta.validation.constraints.*; +import java.io.Serializable; +import java.util.Objects; + +/** + * A DTO for the {@link com.example.questionbank.domain.Subject} entity. + */ +@SuppressWarnings("common-java:DuplicatedBlocks") +public class SubjectDTO implements Serializable { + + private Long id; + + @NotNull + @Size(min = 2, max = 100) + private String name; + + @Size(max = 1000) + private String description; + + @NotNull + private Boolean active; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SubjectDTO)) { + return false; + } + + SubjectDTO subjectDTO = (SubjectDTO) o; + if (this.id == null) { + return false; + } + return Objects.equals(this.id, subjectDTO.id); + } + + @Override + public int hashCode() { + return Objects.hash(this.id); + } + + // prettier-ignore + @Override + public String toString() { + return "SubjectDTO{" + + "id=" + getId() + + ", name='" + getName() + "'" + + ", description='" + getDescription() + "'" + + ", active='" + getActive() + "'" + + "}"; + } +} diff --git a/src/main/java/com/example/questionbank/service/mapper/ChoiceMapper.java b/src/main/java/com/example/questionbank/service/mapper/ChoiceMapper.java new file mode 100644 index 0000000..2d9698c --- /dev/null +++ b/src/main/java/com/example/questionbank/service/mapper/ChoiceMapper.java @@ -0,0 +1,21 @@ +package com.example.questionbank.service.mapper; + +import com.example.questionbank.domain.Choice; +import com.example.questionbank.domain.Question; +import com.example.questionbank.service.dto.ChoiceDTO; +import com.example.questionbank.service.dto.QuestionDTO; +import org.mapstruct.*; + +/** + * Mapper for the entity {@link Choice} and its DTO {@link ChoiceDTO}. + */ +@Mapper(componentModel = "spring") +public interface ChoiceMapper extends EntityMapper { + @Mapping(target = "question", source = "question", qualifiedByName = "questionId") + ChoiceDTO toDto(Choice s); + + @Named("questionId") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + QuestionDTO toDtoQuestionId(Question question); +} diff --git a/src/main/java/com/example/questionbank/service/mapper/EntityMapper.java b/src/main/java/com/example/questionbank/service/mapper/EntityMapper.java new file mode 100644 index 0000000..1968682 --- /dev/null +++ b/src/main/java/com/example/questionbank/service/mapper/EntityMapper.java @@ -0,0 +1,28 @@ +package com.example.questionbank.service.mapper; + +import java.util.List; +import org.mapstruct.BeanMapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.Named; +import org.mapstruct.NullValuePropertyMappingStrategy; + +/** + * Contract for a generic dto to entity mapper. + * + * @param - DTO type parameter. + * @param - Entity type parameter. + */ + +public interface EntityMapper { + E toEntity(D dto); + + D toDto(E entity); + + List toEntity(List dtoList); + + List toDto(List entityList); + + @Named("partialUpdate") + @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) + void partialUpdate(@MappingTarget E entity, D dto); +} diff --git a/src/main/java/com/example/questionbank/service/mapper/ExamAnswerMapper.java b/src/main/java/com/example/questionbank/service/mapper/ExamAnswerMapper.java new file mode 100644 index 0000000..74a3dce --- /dev/null +++ b/src/main/java/com/example/questionbank/service/mapper/ExamAnswerMapper.java @@ -0,0 +1,29 @@ +package com.example.questionbank.service.mapper; + +import com.example.questionbank.domain.ExamAnswer; +import com.example.questionbank.domain.ExamAttempt; +import com.example.questionbank.domain.Question; +import com.example.questionbank.service.dto.ExamAnswerDTO; +import com.example.questionbank.service.dto.ExamAttemptDTO; +import com.example.questionbank.service.dto.QuestionDTO; +import org.mapstruct.*; + +/** + * Mapper for the entity {@link ExamAnswer} and its DTO {@link ExamAnswerDTO}. + */ +@Mapper(componentModel = "spring") +public interface ExamAnswerMapper extends EntityMapper { + @Mapping(target = "question", source = "question", qualifiedByName = "questionId") + @Mapping(target = "attempt", source = "attempt", qualifiedByName = "examAttemptId") + ExamAnswerDTO toDto(ExamAnswer s); + + @Named("questionId") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + QuestionDTO toDtoQuestionId(Question question); + + @Named("examAttemptId") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + ExamAttemptDTO toDtoExamAttemptId(ExamAttempt examAttempt); +} diff --git a/src/main/java/com/example/questionbank/service/mapper/ExamAttemptMapper.java b/src/main/java/com/example/questionbank/service/mapper/ExamAttemptMapper.java new file mode 100644 index 0000000..015194f --- /dev/null +++ b/src/main/java/com/example/questionbank/service/mapper/ExamAttemptMapper.java @@ -0,0 +1,31 @@ +package com.example.questionbank.service.mapper; + +import com.example.questionbank.domain.ExamAttempt; +import com.example.questionbank.domain.Subject; +import com.example.questionbank.domain.User; +import com.example.questionbank.service.dto.ExamAttemptDTO; +import com.example.questionbank.service.dto.SubjectDTO; +import com.example.questionbank.service.dto.UserDTO; +import org.mapstruct.*; + +/** + * Mapper for the entity {@link ExamAttempt} and its DTO {@link ExamAttemptDTO}. + */ +@Mapper(componentModel = "spring") +public interface ExamAttemptMapper extends EntityMapper { + @Mapping(target = "subject", source = "subject", qualifiedByName = "subjectName") + @Mapping(target = "user", source = "user", qualifiedByName = "userLogin") + ExamAttemptDTO toDto(ExamAttempt s); + + @Named("subjectName") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + @Mapping(target = "name", source = "name") + SubjectDTO toDtoSubjectName(Subject subject); + + @Named("userLogin") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + @Mapping(target = "login", source = "login") + UserDTO toDtoUserLogin(User user); +} diff --git a/src/main/java/com/example/questionbank/service/mapper/QuestionMapper.java b/src/main/java/com/example/questionbank/service/mapper/QuestionMapper.java new file mode 100644 index 0000000..2291d3e --- /dev/null +++ b/src/main/java/com/example/questionbank/service/mapper/QuestionMapper.java @@ -0,0 +1,22 @@ +package com.example.questionbank.service.mapper; + +import com.example.questionbank.domain.Question; +import com.example.questionbank.domain.Subject; +import com.example.questionbank.service.dto.QuestionDTO; +import com.example.questionbank.service.dto.SubjectDTO; +import org.mapstruct.*; + +/** + * Mapper for the entity {@link Question} and its DTO {@link QuestionDTO}. + */ +@Mapper(componentModel = "spring") +public interface QuestionMapper extends EntityMapper { + @Mapping(target = "subject", source = "subject", qualifiedByName = "subjectName") + QuestionDTO toDto(Question s); + + @Named("subjectName") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + @Mapping(target = "name", source = "name") + SubjectDTO toDtoSubjectName(Subject subject); +} diff --git a/src/main/java/com/example/questionbank/service/mapper/SubjectMapper.java b/src/main/java/com/example/questionbank/service/mapper/SubjectMapper.java new file mode 100644 index 0000000..8f0088c --- /dev/null +++ b/src/main/java/com/example/questionbank/service/mapper/SubjectMapper.java @@ -0,0 +1,11 @@ +package com.example.questionbank.service.mapper; + +import com.example.questionbank.domain.Subject; +import com.example.questionbank.service.dto.SubjectDTO; +import org.mapstruct.*; + +/** + * Mapper for the entity {@link Subject} and its DTO {@link SubjectDTO}. + */ +@Mapper(componentModel = "spring") +public interface SubjectMapper extends EntityMapper {} diff --git a/src/main/java/com/example/questionbank/web/rest/ChoiceResource.java b/src/main/java/com/example/questionbank/web/rest/ChoiceResource.java new file mode 100644 index 0000000..c65e259 --- /dev/null +++ b/src/main/java/com/example/questionbank/web/rest/ChoiceResource.java @@ -0,0 +1,171 @@ +package com.example.questionbank.web.rest; + +import com.example.questionbank.repository.ChoiceRepository; +import com.example.questionbank.service.ChoiceService; +import com.example.questionbank.service.dto.ChoiceDTO; +import com.example.questionbank.web.rest.errors.BadRequestAlertException; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.example.questionbank.domain.Choice}. + */ +@RestController +@RequestMapping("/api/choices") +public class ChoiceResource { + + private static final Logger LOG = LoggerFactory.getLogger(ChoiceResource.class); + + private static final String ENTITY_NAME = "choice"; + + @Value("${jhipster.clientApp.name:questionBank}") + private String applicationName; + + private final ChoiceService choiceService; + + private final ChoiceRepository choiceRepository; + + public ChoiceResource(ChoiceService choiceService, ChoiceRepository choiceRepository) { + this.choiceService = choiceService; + this.choiceRepository = choiceRepository; + } + + /** + * {@code POST /choices} : Create a new choice. + * + * @param choiceDTO the choiceDTO to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new choiceDTO, or with status {@code 400 (Bad Request)} if the choice has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createChoice(@Valid @RequestBody ChoiceDTO choiceDTO) throws URISyntaxException { + LOG.debug("REST request to save Choice : {}", choiceDTO); + if (choiceDTO.getId() != null) { + throw new BadRequestAlertException("A new choice cannot already have an ID", ENTITY_NAME, "idexists"); + } + choiceDTO = choiceService.save(choiceDTO); + return ResponseEntity.created(new URI("/api/choices/" + choiceDTO.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, choiceDTO.getId().toString())) + .body(choiceDTO); + } + + /** + * {@code PUT /choices/:id} : Updates an existing choice. + * + * @param id the id of the choiceDTO to save. + * @param choiceDTO the choiceDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated choiceDTO, + * or with status {@code 400 (Bad Request)} if the choiceDTO is not valid, + * or with status {@code 500 (Internal Server Error)} if the choiceDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateChoice( + @PathVariable(value = "id", required = false) final Long id, + @Valid @RequestBody ChoiceDTO choiceDTO + ) throws URISyntaxException { + LOG.debug("REST request to update Choice : {}, {}", id, choiceDTO); + if (choiceDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, choiceDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!choiceRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + choiceDTO = choiceService.update(choiceDTO); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, choiceDTO.getId().toString())) + .body(choiceDTO); + } + + /** + * {@code PATCH /choices/:id} : Partial updates given fields of an existing choice, field will ignore if it is null + * + * @param id the id of the choiceDTO to save. + * @param choiceDTO the choiceDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated choiceDTO, + * or with status {@code 400 (Bad Request)} if the choiceDTO is not valid, + * or with status {@code 404 (Not Found)} if the choiceDTO is not found, + * or with status {@code 500 (Internal Server Error)} if the choiceDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateChoice( + @PathVariable(value = "id", required = false) final Long id, + @NotNull @RequestBody ChoiceDTO choiceDTO + ) throws URISyntaxException { + LOG.debug("REST request to partial update Choice partially : {}, {}", id, choiceDTO); + if (choiceDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, choiceDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!choiceRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = choiceService.partialUpdate(choiceDTO); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, choiceDTO.getId().toString()) + ); + } + + /** + * {@code GET /choices} : get all the Choices. + * + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of Choices in body. + */ + @GetMapping("") + public List getAllChoices() { + LOG.debug("REST request to get all Choices"); + return choiceService.findAll(); + } + + /** + * {@code GET /choices/:id} : get the "id" choice. + * + * @param id the id of the choiceDTO to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the choiceDTO, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getChoice(@PathVariable("id") Long id) { + LOG.debug("REST request to get Choice : {}", id); + Optional choiceDTO = choiceService.findOne(id); + return ResponseUtil.wrapOrNotFound(choiceDTO); + } + + /** + * {@code DELETE /choices/:id} : delete the "id" choice. + * + * @param id the id of the choiceDTO to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteChoice(@PathVariable("id") Long id) { + LOG.debug("REST request to delete Choice : {}", id); + choiceService.delete(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/java/com/example/questionbank/web/rest/ExamAnswerResource.java b/src/main/java/com/example/questionbank/web/rest/ExamAnswerResource.java new file mode 100644 index 0000000..5c6de33 --- /dev/null +++ b/src/main/java/com/example/questionbank/web/rest/ExamAnswerResource.java @@ -0,0 +1,171 @@ +package com.example.questionbank.web.rest; + +import com.example.questionbank.repository.ExamAnswerRepository; +import com.example.questionbank.service.ExamAnswerService; +import com.example.questionbank.service.dto.ExamAnswerDTO; +import com.example.questionbank.web.rest.errors.BadRequestAlertException; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.example.questionbank.domain.ExamAnswer}. + */ +@RestController +@RequestMapping("/api/exam-answers") +public class ExamAnswerResource { + + private static final Logger LOG = LoggerFactory.getLogger(ExamAnswerResource.class); + + private static final String ENTITY_NAME = "examAnswer"; + + @Value("${jhipster.clientApp.name:questionBank}") + private String applicationName; + + private final ExamAnswerService examAnswerService; + + private final ExamAnswerRepository examAnswerRepository; + + public ExamAnswerResource(ExamAnswerService examAnswerService, ExamAnswerRepository examAnswerRepository) { + this.examAnswerService = examAnswerService; + this.examAnswerRepository = examAnswerRepository; + } + + /** + * {@code POST /exam-answers} : Create a new examAnswer. + * + * @param examAnswerDTO the examAnswerDTO to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new examAnswerDTO, or with status {@code 400 (Bad Request)} if the examAnswer has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createExamAnswer(@Valid @RequestBody ExamAnswerDTO examAnswerDTO) throws URISyntaxException { + LOG.debug("REST request to save ExamAnswer : {}", examAnswerDTO); + if (examAnswerDTO.getId() != null) { + throw new BadRequestAlertException("A new examAnswer cannot already have an ID", ENTITY_NAME, "idexists"); + } + examAnswerDTO = examAnswerService.save(examAnswerDTO); + return ResponseEntity.created(new URI("/api/exam-answers/" + examAnswerDTO.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, examAnswerDTO.getId().toString())) + .body(examAnswerDTO); + } + + /** + * {@code PUT /exam-answers/:id} : Updates an existing examAnswer. + * + * @param id the id of the examAnswerDTO to save. + * @param examAnswerDTO the examAnswerDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated examAnswerDTO, + * or with status {@code 400 (Bad Request)} if the examAnswerDTO is not valid, + * or with status {@code 500 (Internal Server Error)} if the examAnswerDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateExamAnswer( + @PathVariable(value = "id", required = false) final Long id, + @Valid @RequestBody ExamAnswerDTO examAnswerDTO + ) throws URISyntaxException { + LOG.debug("REST request to update ExamAnswer : {}, {}", id, examAnswerDTO); + if (examAnswerDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, examAnswerDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!examAnswerRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + examAnswerDTO = examAnswerService.update(examAnswerDTO); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, examAnswerDTO.getId().toString())) + .body(examAnswerDTO); + } + + /** + * {@code PATCH /exam-answers/:id} : Partial updates given fields of an existing examAnswer, field will ignore if it is null + * + * @param id the id of the examAnswerDTO to save. + * @param examAnswerDTO the examAnswerDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated examAnswerDTO, + * or with status {@code 400 (Bad Request)} if the examAnswerDTO is not valid, + * or with status {@code 404 (Not Found)} if the examAnswerDTO is not found, + * or with status {@code 500 (Internal Server Error)} if the examAnswerDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateExamAnswer( + @PathVariable(value = "id", required = false) final Long id, + @NotNull @RequestBody ExamAnswerDTO examAnswerDTO + ) throws URISyntaxException { + LOG.debug("REST request to partial update ExamAnswer partially : {}, {}", id, examAnswerDTO); + if (examAnswerDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, examAnswerDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!examAnswerRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = examAnswerService.partialUpdate(examAnswerDTO); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, examAnswerDTO.getId().toString()) + ); + } + + /** + * {@code GET /exam-answers} : get all the Exam Answers. + * + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of Exam Answers in body. + */ + @GetMapping("") + public List getAllExamAnswers() { + LOG.debug("REST request to get all ExamAnswers"); + return examAnswerService.findAll(); + } + + /** + * {@code GET /exam-answers/:id} : get the "id" examAnswer. + * + * @param id the id of the examAnswerDTO to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the examAnswerDTO, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getExamAnswer(@PathVariable("id") Long id) { + LOG.debug("REST request to get ExamAnswer : {}", id); + Optional examAnswerDTO = examAnswerService.findOne(id); + return ResponseUtil.wrapOrNotFound(examAnswerDTO); + } + + /** + * {@code DELETE /exam-answers/:id} : delete the "id" examAnswer. + * + * @param id the id of the examAnswerDTO to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteExamAnswer(@PathVariable("id") Long id) { + LOG.debug("REST request to delete ExamAnswer : {}", id); + examAnswerService.delete(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/java/com/example/questionbank/web/rest/ExamAttemptResource.java b/src/main/java/com/example/questionbank/web/rest/ExamAttemptResource.java new file mode 100644 index 0000000..aa60695 --- /dev/null +++ b/src/main/java/com/example/questionbank/web/rest/ExamAttemptResource.java @@ -0,0 +1,188 @@ +package com.example.questionbank.web.rest; + +import com.example.questionbank.repository.ExamAttemptRepository; +import com.example.questionbank.service.ExamAttemptService; +import com.example.questionbank.service.dto.ExamAttemptDTO; +import com.example.questionbank.web.rest.errors.BadRequestAlertException; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.PaginationUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.example.questionbank.domain.ExamAttempt}. + */ +@RestController +@RequestMapping("/api/exam-attempts") +public class ExamAttemptResource { + + private static final Logger LOG = LoggerFactory.getLogger(ExamAttemptResource.class); + + private static final String ENTITY_NAME = "examAttempt"; + + @Value("${jhipster.clientApp.name:questionBank}") + private String applicationName; + + private final ExamAttemptService examAttemptService; + + private final ExamAttemptRepository examAttemptRepository; + + public ExamAttemptResource(ExamAttemptService examAttemptService, ExamAttemptRepository examAttemptRepository) { + this.examAttemptService = examAttemptService; + this.examAttemptRepository = examAttemptRepository; + } + + /** + * {@code POST /exam-attempts} : Create a new examAttempt. + * + * @param examAttemptDTO the examAttemptDTO to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new examAttemptDTO, or with status {@code 400 (Bad Request)} if the examAttempt has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createExamAttempt(@Valid @RequestBody ExamAttemptDTO examAttemptDTO) throws URISyntaxException { + LOG.debug("REST request to save ExamAttempt : {}", examAttemptDTO); + if (examAttemptDTO.getId() != null) { + throw new BadRequestAlertException("A new examAttempt cannot already have an ID", ENTITY_NAME, "idexists"); + } + examAttemptDTO = examAttemptService.save(examAttemptDTO); + return ResponseEntity.created(new URI("/api/exam-attempts/" + examAttemptDTO.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, examAttemptDTO.getId().toString())) + .body(examAttemptDTO); + } + + /** + * {@code PUT /exam-attempts/:id} : Updates an existing examAttempt. + * + * @param id the id of the examAttemptDTO to save. + * @param examAttemptDTO the examAttemptDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated examAttemptDTO, + * or with status {@code 400 (Bad Request)} if the examAttemptDTO is not valid, + * or with status {@code 500 (Internal Server Error)} if the examAttemptDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateExamAttempt( + @PathVariable(value = "id", required = false) final Long id, + @Valid @RequestBody ExamAttemptDTO examAttemptDTO + ) throws URISyntaxException { + LOG.debug("REST request to update ExamAttempt : {}, {}", id, examAttemptDTO); + if (examAttemptDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, examAttemptDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!examAttemptRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + examAttemptDTO = examAttemptService.update(examAttemptDTO); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, examAttemptDTO.getId().toString())) + .body(examAttemptDTO); + } + + /** + * {@code PATCH /exam-attempts/:id} : Partial updates given fields of an existing examAttempt, field will ignore if it is null + * + * @param id the id of the examAttemptDTO to save. + * @param examAttemptDTO the examAttemptDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated examAttemptDTO, + * or with status {@code 400 (Bad Request)} if the examAttemptDTO is not valid, + * or with status {@code 404 (Not Found)} if the examAttemptDTO is not found, + * or with status {@code 500 (Internal Server Error)} if the examAttemptDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateExamAttempt( + @PathVariable(value = "id", required = false) final Long id, + @NotNull @RequestBody ExamAttemptDTO examAttemptDTO + ) throws URISyntaxException { + LOG.debug("REST request to partial update ExamAttempt partially : {}, {}", id, examAttemptDTO); + if (examAttemptDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, examAttemptDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!examAttemptRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = examAttemptService.partialUpdate(examAttemptDTO); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, examAttemptDTO.getId().toString()) + ); + } + + /** + * {@code GET /exam-attempts} : get all the Exam Attempts. + * + * @param pageable the pagination information. + * @param eagerload flag to eager load entities from relationships (This is applicable for many-to-many). + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of Exam Attempts in body. + */ + @GetMapping("") + public ResponseEntity> getAllExamAttempts( + @org.springdoc.core.annotations.ParameterObject Pageable pageable, + @RequestParam(name = "eagerload", required = false, defaultValue = "true") boolean eagerload + ) { + LOG.debug("REST request to get a page of ExamAttempts"); + Page page; + if (eagerload) { + page = examAttemptService.findAllWithEagerRelationships(pageable); + } else { + page = examAttemptService.findAll(pageable); + } + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); + return ResponseEntity.ok().headers(headers).body(page.getContent()); + } + + /** + * {@code GET /exam-attempts/:id} : get the "id" examAttempt. + * + * @param id the id of the examAttemptDTO to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the examAttemptDTO, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getExamAttempt(@PathVariable("id") Long id) { + LOG.debug("REST request to get ExamAttempt : {}", id); + Optional examAttemptDTO = examAttemptService.findOne(id); + return ResponseUtil.wrapOrNotFound(examAttemptDTO); + } + + /** + * {@code DELETE /exam-attempts/:id} : delete the "id" examAttempt. + * + * @param id the id of the examAttemptDTO to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteExamAttempt(@PathVariable("id") Long id) { + LOG.debug("REST request to delete ExamAttempt : {}", id); + examAttemptService.delete(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/java/com/example/questionbank/web/rest/QuestionResource.java b/src/main/java/com/example/questionbank/web/rest/QuestionResource.java new file mode 100644 index 0000000..407e850 --- /dev/null +++ b/src/main/java/com/example/questionbank/web/rest/QuestionResource.java @@ -0,0 +1,188 @@ +package com.example.questionbank.web.rest; + +import com.example.questionbank.repository.QuestionRepository; +import com.example.questionbank.service.QuestionService; +import com.example.questionbank.service.dto.QuestionDTO; +import com.example.questionbank.web.rest.errors.BadRequestAlertException; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.PaginationUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.example.questionbank.domain.Question}. + */ +@RestController +@RequestMapping("/api/questions") +public class QuestionResource { + + private static final Logger LOG = LoggerFactory.getLogger(QuestionResource.class); + + private static final String ENTITY_NAME = "question"; + + @Value("${jhipster.clientApp.name:questionBank}") + private String applicationName; + + private final QuestionService questionService; + + private final QuestionRepository questionRepository; + + public QuestionResource(QuestionService questionService, QuestionRepository questionRepository) { + this.questionService = questionService; + this.questionRepository = questionRepository; + } + + /** + * {@code POST /questions} : Create a new question. + * + * @param questionDTO the questionDTO to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new questionDTO, or with status {@code 400 (Bad Request)} if the question has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createQuestion(@Valid @RequestBody QuestionDTO questionDTO) throws URISyntaxException { + LOG.debug("REST request to save Question : {}", questionDTO); + if (questionDTO.getId() != null) { + throw new BadRequestAlertException("A new question cannot already have an ID", ENTITY_NAME, "idexists"); + } + questionDTO = questionService.save(questionDTO); + return ResponseEntity.created(new URI("/api/questions/" + questionDTO.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, questionDTO.getId().toString())) + .body(questionDTO); + } + + /** + * {@code PUT /questions/:id} : Updates an existing question. + * + * @param id the id of the questionDTO to save. + * @param questionDTO the questionDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated questionDTO, + * or with status {@code 400 (Bad Request)} if the questionDTO is not valid, + * or with status {@code 500 (Internal Server Error)} if the questionDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateQuestion( + @PathVariable(value = "id", required = false) final Long id, + @Valid @RequestBody QuestionDTO questionDTO + ) throws URISyntaxException { + LOG.debug("REST request to update Question : {}, {}", id, questionDTO); + if (questionDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, questionDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!questionRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + questionDTO = questionService.update(questionDTO); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, questionDTO.getId().toString())) + .body(questionDTO); + } + + /** + * {@code PATCH /questions/:id} : Partial updates given fields of an existing question, field will ignore if it is null + * + * @param id the id of the questionDTO to save. + * @param questionDTO the questionDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated questionDTO, + * or with status {@code 400 (Bad Request)} if the questionDTO is not valid, + * or with status {@code 404 (Not Found)} if the questionDTO is not found, + * or with status {@code 500 (Internal Server Error)} if the questionDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateQuestion( + @PathVariable(value = "id", required = false) final Long id, + @NotNull @RequestBody QuestionDTO questionDTO + ) throws URISyntaxException { + LOG.debug("REST request to partial update Question partially : {}, {}", id, questionDTO); + if (questionDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, questionDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!questionRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = questionService.partialUpdate(questionDTO); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, questionDTO.getId().toString()) + ); + } + + /** + * {@code GET /questions} : get all the Questions. + * + * @param pageable the pagination information. + * @param eagerload flag to eager load entities from relationships (This is applicable for many-to-many). + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of Questions in body. + */ + @GetMapping("") + public ResponseEntity> getAllQuestions( + @org.springdoc.core.annotations.ParameterObject Pageable pageable, + @RequestParam(name = "eagerload", required = false, defaultValue = "true") boolean eagerload + ) { + LOG.debug("REST request to get a page of Questions"); + Page page; + if (eagerload) { + page = questionService.findAllWithEagerRelationships(pageable); + } else { + page = questionService.findAll(pageable); + } + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); + return ResponseEntity.ok().headers(headers).body(page.getContent()); + } + + /** + * {@code GET /questions/:id} : get the "id" question. + * + * @param id the id of the questionDTO to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the questionDTO, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getQuestion(@PathVariable("id") Long id) { + LOG.debug("REST request to get Question : {}", id); + Optional questionDTO = questionService.findOne(id); + return ResponseUtil.wrapOrNotFound(questionDTO); + } + + /** + * {@code DELETE /questions/:id} : delete the "id" question. + * + * @param id the id of the questionDTO to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteQuestion(@PathVariable("id") Long id) { + LOG.debug("REST request to delete Question : {}", id); + questionService.delete(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/java/com/example/questionbank/web/rest/SubjectResource.java b/src/main/java/com/example/questionbank/web/rest/SubjectResource.java new file mode 100644 index 0000000..801370c --- /dev/null +++ b/src/main/java/com/example/questionbank/web/rest/SubjectResource.java @@ -0,0 +1,179 @@ +package com.example.questionbank.web.rest; + +import com.example.questionbank.repository.SubjectRepository; +import com.example.questionbank.service.SubjectService; +import com.example.questionbank.service.dto.SubjectDTO; +import com.example.questionbank.web.rest.errors.BadRequestAlertException; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import tech.jhipster.web.util.HeaderUtil; +import tech.jhipster.web.util.PaginationUtil; +import tech.jhipster.web.util.ResponseUtil; + +/** + * REST controller for managing {@link com.example.questionbank.domain.Subject}. + */ +@RestController +@RequestMapping("/api/subjects") +public class SubjectResource { + + private static final Logger LOG = LoggerFactory.getLogger(SubjectResource.class); + + private static final String ENTITY_NAME = "subject"; + + @Value("${jhipster.clientApp.name:questionBank}") + private String applicationName; + + private final SubjectService subjectService; + + private final SubjectRepository subjectRepository; + + public SubjectResource(SubjectService subjectService, SubjectRepository subjectRepository) { + this.subjectService = subjectService; + this.subjectRepository = subjectRepository; + } + + /** + * {@code POST /subjects} : Create a new subject. + * + * @param subjectDTO the subjectDTO to create. + * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new subjectDTO, or with status {@code 400 (Bad Request)} if the subject has already an ID. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PostMapping("") + public ResponseEntity createSubject(@Valid @RequestBody SubjectDTO subjectDTO) throws URISyntaxException { + LOG.debug("REST request to save Subject : {}", subjectDTO); + if (subjectDTO.getId() != null) { + throw new BadRequestAlertException("A new subject cannot already have an ID", ENTITY_NAME, "idexists"); + } + subjectDTO = subjectService.save(subjectDTO); + return ResponseEntity.created(new URI("/api/subjects/" + subjectDTO.getId())) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, subjectDTO.getId().toString())) + .body(subjectDTO); + } + + /** + * {@code PUT /subjects/:id} : Updates an existing subject. + * + * @param id the id of the subjectDTO to save. + * @param subjectDTO the subjectDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated subjectDTO, + * or with status {@code 400 (Bad Request)} if the subjectDTO is not valid, + * or with status {@code 500 (Internal Server Error)} if the subjectDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PutMapping("/{id}") + public ResponseEntity updateSubject( + @PathVariable(value = "id", required = false) final Long id, + @Valid @RequestBody SubjectDTO subjectDTO + ) throws URISyntaxException { + LOG.debug("REST request to update Subject : {}, {}", id, subjectDTO); + if (subjectDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, subjectDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!subjectRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + subjectDTO = subjectService.update(subjectDTO); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, subjectDTO.getId().toString())) + .body(subjectDTO); + } + + /** + * {@code PATCH /subjects/:id} : Partial updates given fields of an existing subject, field will ignore if it is null + * + * @param id the id of the subjectDTO to save. + * @param subjectDTO the subjectDTO to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated subjectDTO, + * or with status {@code 400 (Bad Request)} if the subjectDTO is not valid, + * or with status {@code 404 (Not Found)} if the subjectDTO is not found, + * or with status {@code 500 (Internal Server Error)} if the subjectDTO couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = "/{id}", consumes = { "application/json", "application/merge-patch+json" }) + public ResponseEntity partialUpdateSubject( + @PathVariable(value = "id", required = false) final Long id, + @NotNull @RequestBody SubjectDTO subjectDTO + ) throws URISyntaxException { + LOG.debug("REST request to partial update Subject partially : {}, {}", id, subjectDTO); + if (subjectDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + if (!Objects.equals(id, subjectDTO.getId())) { + throw new BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid"); + } + + if (!subjectRepository.existsById(id)) { + throw new BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound"); + } + + Optional result = subjectService.partialUpdate(subjectDTO); + + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, subjectDTO.getId().toString()) + ); + } + + /** + * {@code GET /subjects} : get all the Subjects. + * + * @param pageable the pagination information. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of Subjects in body. + */ + @GetMapping("") + public ResponseEntity> getAllSubjects(@org.springdoc.core.annotations.ParameterObject Pageable pageable) { + LOG.debug("REST request to get a page of Subjects"); + Page page = subjectService.findAll(pageable); + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); + return ResponseEntity.ok().headers(headers).body(page.getContent()); + } + + /** + * {@code GET /subjects/:id} : get the "id" subject. + * + * @param id the id of the subjectDTO to retrieve. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the subjectDTO, or with status {@code 404 (Not Found)}. + */ + @GetMapping("/{id}") + public ResponseEntity getSubject(@PathVariable("id") Long id) { + LOG.debug("REST request to get Subject : {}", id); + Optional subjectDTO = subjectService.findOne(id); + return ResponseUtil.wrapOrNotFound(subjectDTO); + } + + /** + * {@code DELETE /subjects/:id} : delete the "id" subject. + * + * @param id the id of the subjectDTO to delete. + * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteSubject(@PathVariable("id") Long id) { + LOG.debug("REST request to delete Subject : {}", id); + subjectService.delete(id); + return ResponseEntity.noContent() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())) + .build(); + } +} diff --git a/src/main/resources/config/liquibase/changelog/20261020093322_added_entity_Subject.xml b/src/main/resources/config/liquibase/changelog/20261020093322_added_entity_Subject.xml new file mode 100644 index 0000000..fde5192 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093322_added_entity_Subject.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093323_added_entity_Question.xml b/src/main/resources/config/liquibase/changelog/20261020093323_added_entity_Question.xml new file mode 100644 index 0000000..22ed0be --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093323_added_entity_Question.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093323_added_entity_constraints_Question.xml b/src/main/resources/config/liquibase/changelog/20261020093323_added_entity_constraints_Question.xml new file mode 100644 index 0000000..f42f617 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093323_added_entity_constraints_Question.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093324_added_entity_Choice.xml b/src/main/resources/config/liquibase/changelog/20261020093324_added_entity_Choice.xml new file mode 100644 index 0000000..043060a --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093324_added_entity_Choice.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093324_added_entity_constraints_Choice.xml b/src/main/resources/config/liquibase/changelog/20261020093324_added_entity_constraints_Choice.xml new file mode 100644 index 0000000..32a0132 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093324_added_entity_constraints_Choice.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093325_added_entity_ExamAttempt.xml b/src/main/resources/config/liquibase/changelog/20261020093325_added_entity_ExamAttempt.xml new file mode 100644 index 0000000..2078413 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093325_added_entity_ExamAttempt.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093325_added_entity_constraints_ExamAttempt.xml b/src/main/resources/config/liquibase/changelog/20261020093325_added_entity_constraints_ExamAttempt.xml new file mode 100644 index 0000000..e03b71f --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093325_added_entity_constraints_ExamAttempt.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093326_added_entity_ExamAnswer.xml b/src/main/resources/config/liquibase/changelog/20261020093326_added_entity_ExamAnswer.xml new file mode 100644 index 0000000..aa871ea --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093326_added_entity_ExamAnswer.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/changelog/20261020093326_added_entity_constraints_ExamAnswer.xml b/src/main/resources/config/liquibase/changelog/20261020093326_added_entity_constraints_ExamAnswer.xml new file mode 100644 index 0000000..357340d --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20261020093326_added_entity_constraints_ExamAnswer.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/fake-data/choice.csv b/src/main/resources/config/liquibase/fake-data/choice.csv new file mode 100644 index 0000000..2e2a222 --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/choice.csv @@ -0,0 +1,31 @@ +id;option_key;content;display_order;correct;question_id +1;A;with costume;2;true;1 +2;A;lid deceivingly sequester;2;false;2 +3;C;noxious bah;2;true;3 +4;C;reluctantly for;4;true;4 +5;C;focalise;3;false;5 +6;D;unto deduce;2;true;6 +7;A;appropriate;3;true;7 +8;D;notwithstanding floodlight carefully;1;false;8 +9;C;eek switch;1;true;9 +10;C;frivolous;2;false;10 +11;C;unlike internal;1;true;11 +12;D;not finally cauliflower;3;true;12 +13;D;snoop athwart;4;true;13 +14;A;silt;4;false;14 +15;A;lady ew;2;true;15 +16;A;beautifully kettledrum;3;false;16 +17;A;fervently vaguely;3;false;17 +18;C;orchid flu;2;true;18 +19;C;yellowish boohoo;4;false;19 +20;B;unzip density;3;false;20 +21;B;oof;3;false;21 +22;C;brr before;4;true;22 +23;C;fondly;2;true;23 +24;C;juvenile;4;true;24 +25;B;before;4;false;25 +26;B;bathhouse pro once;2;true;26 +27;D;now infinite;1;true;27 +28;D;enraged wicked;3;true;28 +29;C;hmph;3;false;29 +30;C;storyboard until;3;false;30 diff --git a/src/main/resources/config/liquibase/fake-data/exam_answer.csv b/src/main/resources/config/liquibase/fake-data/exam_answer.csv new file mode 100644 index 0000000..a18e6cc --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/exam_answer.csv @@ -0,0 +1,31 @@ +id;question_text_snapshot;explanation_snapshot;selected_option;selected_content_snapshot;correct;awarded_points;question_id;attempt_id +1;ugh;toward;D;ick;true;12587;1;1 +2;till woot;always;A;bin;true;16466;2;2 +3;serpentine;violently circa;C;pinstripe;true;10708;3;3 +4;down that deform;nor;B;as misfire fat;true;11576;4;4 +5;riser oddly;but upbeat yahoo;A;however conjecture failing;true;13031;5;5 +6;now;hydrolyse;D;founder even gosh;false;24241;6;6 +7;pfft till broadcast;under absentmindedly unto;D;enlist but when;false;20728;7;7 +8;internal versus;curiously pocket-watch;D;alongside;true;25319;8;8 +9;follower vice agreement;sunbeam ah;D;woot monthly maestro;false;25579;9;9 +10;aha mortise flawed;ha meanwhile but;B;pigsty musty;false;30644;10;10 +11;circa scoff delete;decisive outlandish yellowish;D;atop where aside;true;7833;11;11 +12;optimistically;character apropos;D;until horn till;true;29173;12;12 +13;carefully scale;agreeable loose teammate;A;scale circa;false;14408;13;13 +14;known since boohoo;fortunate tarry;C;crossly;true;23661;14;14 +15;whoever thongs dime;meh bashfully zowie;C;woot kiss even;false;2961;15;15 +16;fledgling;illiterate daily versus;B;rarely consequently;true;32555;16;16 +17;actual thoroughly tightly;phooey vol;A;save;true;3135;17;17 +18;now whereas plan;besides once;D;incidentally outstanding;true;6047;18;18 +19;foolishly shrilly woot;nor;C;foolhardy;false;992;19;19 +20;against;mixed during;C;limited boohoo;false;20306;20;20 +21;instead serene jealous;out an;C;lest utter;false;6732;21;21 +22;drat;edge following fervently;A;reassuringly qua or;true;17883;22;22 +23;implode hence;divert but;A;which blindly;false;13140;23;23 +24;miserable because detective;industrialize;D;forceful harmful;false;13920;24;24 +25;whoever instantly purse;sign legislature save;D;faithfully despite until;true;5194;25;25 +26;unto;oof;D;heavy above bathhouse;false;822;26;26 +27;gah whoever woot;rubbery exonerate once;D;house;true;1962;27;27 +28;carboxyl meal astride;round eek;D;transplant;false;9840;28;28 +29;delectable;sideboard;C;failing;true;27119;29;29 +30;ruin pike;above impressionable instead;A;gallivant however;true;25196;30;30 diff --git a/src/main/resources/config/liquibase/fake-data/exam_attempt.csv b/src/main/resources/config/liquibase/fake-data/exam_attempt.csv new file mode 100644 index 0000000..95ab945 --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/exam_attempt.csv @@ -0,0 +1,31 @@ +id;started_at;submitted_at;status;score;subject_id;user_id +1;2026-10-20T05:13:21;2026-10-20T01:17:36;SUBMITTED;3734;1;1 +2;2026-10-19T09:47:49;2026-10-20T05:21:23;IN_PROGRESS;28602;2;2 +3;2026-10-19T12:45:47;2026-10-19T16:22:03;SUBMITTED;27107;3;1 +4;2026-10-20T08:43:34;2026-10-20T06:21:59;IN_PROGRESS;7700;4;2 +5;2026-10-20T05:35:25;2026-10-20T07:22:22;IN_PROGRESS;25958;5;1 +6;2026-10-20T03:14:45;2026-10-19T11:15:55;SUBMITTED;11353;6;2 +7;2026-10-19T23:27:46;2026-10-20T08:33:10;SUBMITTED;6060;7;2 +8;2026-10-20T06:49:32;2026-10-19T20:38:10;IN_PROGRESS;16941;8;2 +9;2026-10-19T15:09:55;2026-10-20T05:14:06;SUBMITTED;20866;9;1 +10;2026-10-19T16:39:29;2026-10-19T20:06:46;IN_PROGRESS;16189;10;2 +11;2026-10-20T06:38:28;2026-10-19T22:18:56;SUBMITTED;19064;11;2 +12;2026-10-20T08:04:44;2026-10-19T15:02:59;SUBMITTED;18424;12;1 +13;2026-10-19T10:18:45;2026-10-20T06:20:54;IN_PROGRESS;26938;13;2 +14;2026-10-20T04:10:26;2026-10-20T01:44:42;SUBMITTED;8122;14;1 +15;2026-10-19T18:16:57;2026-10-19T15:22:19;IN_PROGRESS;23873;15;1 +16;2026-10-20T09:07:32;2026-10-20T05:17:47;IN_PROGRESS;9256;16;2 +17;2026-10-20T04:02:47;2026-10-20T09:17:35;SUBMITTED;6982;17;2 +18;2026-10-19T11:17:34;2026-10-20T03:26:21;IN_PROGRESS;25465;18;1 +19;2026-10-20T04:33:44;2026-10-19T21:48:50;SUBMITTED;3984;19;2 +20;2026-10-19T22:18:00;2026-10-19T16:02:57;IN_PROGRESS;4109;20;1 +21;2026-10-20T01:49:34;2026-10-19T17:57:15;IN_PROGRESS;19778;21;2 +22;2026-10-19T12:30:46;2026-10-20T03:16:39;SUBMITTED;14716;22;2 +23;2026-10-19T11:51:17;2026-10-20T04:06:02;SUBMITTED;13292;23;2 +24;2026-10-20T02:30:50;2026-10-20T00:57:33;IN_PROGRESS;7461;24;1 +25;2026-10-20T02:04:10;2026-10-19T15:42:20;IN_PROGRESS;20711;25;1 +26;2026-10-19T18:47:45;2026-10-20T03:42:21;IN_PROGRESS;4861;26;2 +27;2026-10-19T15:38:42;2026-10-20T05:40:30;SUBMITTED;29915;27;2 +28;2026-10-20T06:35:33;2026-10-19T16:47:02;IN_PROGRESS;1705;28;1 +29;2026-10-19T20:45:52;2026-10-20T02:14:03;SUBMITTED;31593;29;1 +30;2026-10-19T23:07:28;2026-10-19T12:20:15;IN_PROGRESS;10042;30;2 diff --git a/src/main/resources/config/liquibase/fake-data/question.csv b/src/main/resources/config/liquibase/fake-data/question.csv new file mode 100644 index 0000000..f6a398d --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/question.csv @@ -0,0 +1,31 @@ +id;prompt;explanation;active;subject_id +1;yuckX;meh;false;1 +2;independence who hasty;pace fledgling idealistic;false;2 +3;yetXX;shyly mid although;true;3 +4;aw unsightly criminal;atop whether absent;false;4 +5;nearly;till phooey which;true;5 +6;embalm;first since brand;true;6 +7;carelessly;reclassify each;true;7 +8;awXXX;publication consequently median;false;8 +9;curiously claw;gaseous phooey athwart;true;9 +10;worth endow simple;unabashedly fork despite;false;10 +11;for airline;immediate inconsequential;false;11 +12;quaver;whether;true;12 +13;oh brr bobble;who sandy;true;13 +14;colorful;graffiti offset;true;14 +15;intrepid;uncork;true;15 +16;plus engage;ah;false;16 +17;because;until nephew via;false;17 +18;slink glass;zowie if loosely;false;18 +19;mom ew;league easy huzzah;true;19 +20;scotch yet;print unlike pfft;true;20 +21;athletic cruel than;given valuable whose;false;21 +22;mad schnitzel;rebel;false;22 +23;tomorrow until though;now almost;true;23 +24;overheard ouch after;anti needily;false;24 +25;meanwhile tensely;minister gee gosh;false;25 +26;intensely psst beside;overcoat because ack;true;26 +27;reword;cluttered boo;false;27 +28;colorfully beneath interestingly;flustered hasty;false;28 +29;kiddingly unimportant uh-huh;deploy;false;29 +30;about toward;revitalise ah decryption;true;30 diff --git a/src/main/resources/config/liquibase/fake-data/subject.csv b/src/main/resources/config/liquibase/fake-data/subject.csv new file mode 100644 index 0000000..3d0a03c --- /dev/null +++ b/src/main/resources/config/liquibase/fake-data/subject.csv @@ -0,0 +1,31 @@ +id;name;description;active +1;indeed atomize pale;practical randomize and;true +2;accompany;per doodle for;true +3;swift zowie amid;continually;false +4;thankfully instead;shout excess fond;true +5;unfreeze configuration;gee unless;false +6;absentmindedly;pro clear lasting;true +7;courageously husk zowie;into;false +8;nougat little accidentally;ick;true +9;what;opposite subtract;false +10;underneath;despite roadway;true +11;officially restfully;guidance;false +12;likewise;boring drat ew;true +13;icebreaker considering upbeat;until across bogus;true +14;natural;ah of;false +15;ugh fax;ferret ack;true +16;longingly drum;nor;false +17;yahoo;doubtfully plan along;true +18;so through;wafer so;true +19;nervous luck;roadway digit;true +20;bare yippee;trolley arbitrate;false +21;uncomfortable;detective;true +22;flustered finally;brr terribly;true +23;a selfishly;biodegradable ew;true +24;ingratiate propound promptly;advocate;true +25;indeed ouch;pfft failing reschedule;false +26;while robust unique;camouflage after now;false +27;source;anenst curse resort;true +28;colorfully um;ugh adventurously;true +29;provided ah;why;false +30;ad along a;tusk;false diff --git a/src/main/resources/config/liquibase/master.xml b/src/main/resources/config/liquibase/master.xml index 315d9ec..8c1c0d0 100644 --- a/src/main/resources/config/liquibase/master.xml +++ b/src/main/resources/config/liquibase/master.xml @@ -12,7 +12,16 @@ + + + + + + + + + diff --git a/src/main/webapp/app/entities/choice/choice-details.component.spec.ts b/src/main/webapp/app/entities/choice/choice-details.component.spec.ts new file mode 100644 index 0000000..8d13e82 --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice-details.component.spec.ts @@ -0,0 +1,91 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ChoiceDetails from './choice-details.vue'; + +type ChoiceDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const choiceSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('Choice Management Detail Component', () => { + let choiceServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + choiceServiceStub = { + find: vi.fn(), + }; + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + choiceService: () => choiceServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + choiceServiceStub.find.mockResolvedValue(choiceSample); + route = { + params: { + choiceId: `${123}`, + }, + }; + const wrapper = shallowMount(ChoiceDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.choice).toMatchObject(choiceSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + choiceServiceStub.find.mockResolvedValue(choiceSample); + const wrapper = shallowMount(ChoiceDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/choice/choice-details.component.ts b/src/main/webapp/app/entities/choice/choice-details.component.ts new file mode 100644 index 0000000..bcaed39 --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice-details.component.ts @@ -0,0 +1,42 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type IChoice } from '@/shared/model/choice.model'; + +import ChoiceService from './choice.service'; + +export default defineComponent({ + name: 'ChoiceDetails', + setup() { + const choiceService = inject('choiceService', () => new ChoiceService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const choice: Ref = ref({}); + + const retrieveChoice = async choiceId => { + try { + const res = await choiceService().find(choiceId); + choice.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.choiceId) { + retrieveChoice(route.params.choiceId); + } + + return { + choice, + + previousState, + t$: useI18n().t, + }; + }, +}); diff --git a/src/main/webapp/app/entities/choice/choice-details.vue b/src/main/webapp/app/entities/choice/choice-details.vue new file mode 100644 index 0000000..cbc6f3e --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice-details.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/main/webapp/app/entities/choice/choice-update.component.spec.ts b/src/main/webapp/app/entities/choice/choice-update.component.spec.ts new file mode 100644 index 0000000..15376d5 --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice-update.component.spec.ts @@ -0,0 +1,139 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ChoiceUpdate from './choice-update.vue'; + +type ChoiceUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const choiceSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('Choice Management Update Component', () => { + let comp: ChoiceUpdateComponentType; + let choiceServiceStub: any; + + beforeEach(() => { + route = {}; + choiceServiceStub = { + retrieve: vi.fn(), + find: vi.fn(), + update: vi.fn(), + create: vi.fn(), + }; + choiceServiceStub.retrieve.mockResolvedValueOnce([]); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + choiceService: () => choiceServiceStub, + questionService: () => ({ + retrieve: vi.fn().mockResolvedValue({}), + }), + }, + }; + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(ChoiceUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.choice = choiceSample; + choiceServiceStub.update.mockResolvedValue(choiceSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(choiceServiceStub.update).toHaveBeenCalledWith(choiceSample); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + choiceServiceStub.create.mockResolvedValue(entity); + const wrapper = shallowMount(ChoiceUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.choice = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(choiceServiceStub.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + choiceServiceStub.find.mockResolvedValue(choiceSample); + choiceServiceStub.retrieve.mockResolvedValue([choiceSample]); + + // WHEN + route = { + params: { + choiceId: `${choiceSample.id}`, + }, + }; + const wrapper = shallowMount(ChoiceUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.choice).toMatchObject(choiceSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + choiceServiceStub.find.mockResolvedValue(choiceSample); + const wrapper = shallowMount(ChoiceUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/choice/choice-update.component.ts b/src/main/webapp/app/entities/choice/choice-update.component.ts new file mode 100644 index 0000000..9f50d2e --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice-update.component.ts @@ -0,0 +1,129 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useVuelidate } from '@vuelidate/core'; + +import QuestionService from '@/entities/question/question.service'; +import { useAlertService } from '@/shared/alert/alert.service'; +import { useValidation } from '@/shared/composables'; +import { Choice, type IChoice } from '@/shared/model/choice.model'; +import { OptionKey } from '@/shared/model/enumerations/option-key.model'; +import { type IQuestion } from '@/shared/model/question.model'; + +import ChoiceService from './choice.service'; + +export default defineComponent({ + name: 'ChoiceUpdate', + setup() { + const choiceService = inject('choiceService', () => new ChoiceService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const choice: Ref = ref(new Choice()); + + const questionService = inject('questionService', () => new QuestionService()); + + const questions: Ref = ref([]); + const optionKeyValues: Ref = ref(Object.keys(OptionKey)); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveChoice = async choiceId => { + try { + const res = await choiceService().find(choiceId); + choice.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.choiceId) { + retrieveChoice(route.params.choiceId); + } + + const initRelationships = () => { + questionService() + .retrieve() + .then(res => { + questions.value = res.data; + }); + }; + + initRelationships(); + + const { t: t$ } = useI18n(); + const validations = useValidation(); + const validationRules = { + optionKey: { + required: validations.required(t$('entity.validation.required').toString()), + }, + content: { + required: validations.required(t$('entity.validation.required').toString()), + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 500 }).toString(), 500), + }, + displayOrder: { + required: validations.required(t$('entity.validation.required').toString()), + integer: validations.integer(t$('entity.validation.number').toString()), + min: validations.minValue(t$('entity.validation.min', { min: 1 }).toString(), 1), + max: validations.maxValue(t$('entity.validation.max', { max: 4 }).toString(), 4), + }, + correct: { + required: validations.required(t$('entity.validation.required').toString()), + }, + question: { + required: validations.required(t$('entity.validation.required').toString()), + }, + }; + const v$ = useVuelidate(validationRules, choice as any); + v$.value.$validate(); + + return { + choiceService, + alertService, + choice, + previousState, + optionKeyValues, + isSaving, + currentLanguage, + questions, + v$, + t$, + }; + }, + created(): void {}, + methods: { + save(): void { + this.isSaving = true; + if (this.choice.id) { + this.choiceService() + .update(this.choice) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(this.t$('questionBankApp.choice.updated', { param: param.id })); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.choiceService() + .create(this.choice) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(this.t$('questionBankApp.choice.created', { param: param.id }).toString()); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + }, +}); diff --git a/src/main/webapp/app/entities/choice/choice-update.vue b/src/main/webapp/app/entities/choice/choice-update.vue new file mode 100644 index 0000000..73f809a --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice-update.vue @@ -0,0 +1,120 @@ + + diff --git a/src/main/webapp/app/entities/choice/choice.component.spec.ts b/src/main/webapp/app/entities/choice/choice.component.spec.ts new file mode 100644 index 0000000..f202803 --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice.component.spec.ts @@ -0,0 +1,103 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import Choice from './choice.vue'; + +type ChoiceComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('Choice Management Component', () => { + let choiceServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + choiceServiceStub = { + retrieve: vi.fn(), + delete: vi.fn(), + }; + choiceServiceStub.retrieve.mockResolvedValue({ headers: {} }); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + choiceService: () => choiceServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + choiceServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(Choice, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(choiceServiceStub.retrieve).toHaveBeenCalledOnce(); + expect(comp.choices[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + }); + describe('Handles', () => { + let comp: ChoiceComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(Choice, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + choiceServiceStub.retrieve.mockReset(); + choiceServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [] }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + choiceServiceStub.delete.mockResolvedValue({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeChoice(); + await comp.$nextTick(); // clear components + + // THEN + expect(choiceServiceStub.delete).toHaveBeenCalled(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(choiceServiceStub.retrieve).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/choice/choice.component.ts b/src/main/webapp/app/entities/choice/choice.component.ts new file mode 100644 index 0000000..82866d8 --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice.component.ts @@ -0,0 +1,78 @@ +import { type Ref, defineComponent, inject, onMounted, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type IChoice } from '@/shared/model/choice.model'; + +import ChoiceService from './choice.service'; + +export default defineComponent({ + name: 'Choice', + setup() { + const { t: t$ } = useI18n(); + const choiceService = inject('choiceService', () => new ChoiceService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const choices: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => {}; + + const retrieveChoices = async () => { + isFetching.value = true; + try { + const res = await choiceService().retrieve(); + choices.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveChoices(); + }; + + onMounted(async () => { + await retrieveChoices(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: IChoice) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeChoice = async () => { + try { + await choiceService().delete(removeId.value); + const message = t$('questionBankApp.choice.deleted', { param: removeId.value }).toString(); + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveChoices(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + return { + choices, + handleSyncList, + isFetching, + retrieveChoices, + clear, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeChoice, + t$, + }; + }, +}); diff --git a/src/main/webapp/app/entities/choice/choice.service.spec.ts b/src/main/webapp/app/entities/choice/choice.service.spec.ts new file mode 100644 index 0000000..74ff6b4 --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice.service.spec.ts @@ -0,0 +1,161 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import axios from 'axios'; + +import { Choice } from '@/shared/model/choice.model'; + +import ChoiceService from './choice.service'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: vi.spyOn(axios, 'get'), + post: vi.spyOn(axios, 'post'), + put: vi.spyOn(axios, 'put'), + patch: vi.spyOn(axios, 'patch'), + delete: vi.spyOn(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('Choice Service', () => { + let service: ChoiceService; + let elemDefault; + + beforeEach(() => { + service = new ChoiceService(); + elemDefault = new Choice(123, 'A', 'AAAAAAA', 0, false); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { ...elemDefault }; + axiosStub.get.mockResolvedValue({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.mockRejectedValue(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a Choice', async () => { + const returnedFromService = { id: 123, ...elemDefault }; + const expected = { ...returnedFromService }; + + axiosStub.post.mockResolvedValue({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a Choice', async () => { + axiosStub.post.mockRejectedValue(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a Choice', async () => { + const returnedFromService = { optionKey: 'BBBBBB', content: 'BBBBBB', displayOrder: 1, correct: true, ...elemDefault }; + + const expected = { ...returnedFromService }; + axiosStub.put.mockResolvedValue({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a Choice', async () => { + axiosStub.put.mockRejectedValue(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a Choice', async () => { + const patchObject = { content: 'BBBBBB', ...new Choice() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { ...returnedFromService }; + axiosStub.patch.mockResolvedValue({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a Choice', async () => { + axiosStub.patch.mockRejectedValue(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of Choice', async () => { + const returnedFromService = { optionKey: 'BBBBBB', content: 'BBBBBB', displayOrder: 1, correct: true, ...elemDefault }; + const expected = { ...returnedFromService }; + axiosStub.get.mockResolvedValue([returnedFromService]); + return service.retrieve().then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of Choice', async () => { + axiosStub.get.mockRejectedValue(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a Choice', async () => { + axiosStub.delete.mockResolvedValue({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a Choice', async () => { + axiosStub.delete.mockRejectedValue(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/choice/choice.service.ts b/src/main/webapp/app/entities/choice/choice.service.ts new file mode 100644 index 0000000..804172f --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice.service.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; + +import { type IChoice } from '@/shared/model/choice.model'; + +const baseApiUrl = 'api/choices'; + +export default class ChoiceService { + find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + retrieve(): Promise { + return new Promise((resolve, reject) => { + axios + .get(baseApiUrl) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + create(entity: IChoice): Promise { + return new Promise((resolve, reject) => { + axios + .post(baseApiUrl, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + update(entity: IChoice): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + partialUpdate(entity: IChoice): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/choice/choice.vue b/src/main/webapp/app/entities/choice/choice.vue new file mode 100644 index 0000000..f47c92b --- /dev/null +++ b/src/main/webapp/app/entities/choice/choice.vue @@ -0,0 +1,117 @@ + + + diff --git a/src/main/webapp/app/entities/entities-menu.vue b/src/main/webapp/app/entities/entities-menu.vue index 22b4569..1ce5cfb 100644 --- a/src/main/webapp/app/entities/entities-menu.vue +++ b/src/main/webapp/app/entities/entities-menu.vue @@ -1,5 +1,25 @@ diff --git a/src/main/webapp/app/entities/entities.component.ts b/src/main/webapp/app/entities/entities.component.ts index 330630b..95d99ea 100644 --- a/src/main/webapp/app/entities/entities.component.ts +++ b/src/main/webapp/app/entities/entities.component.ts @@ -1,12 +1,23 @@ import { defineComponent, provide } from 'vue'; import UserService from '@/entities/user/user.service'; + +import ChoiceService from './choice/choice.service'; +import ExamAnswerService from './exam-answer/exam-answer.service'; +import ExamAttemptService from './exam-attempt/exam-attempt.service'; +import QuestionService from './question/question.service'; +import SubjectService from './subject/subject.service'; // jhipster-needle-add-entity-service-to-entities-component-import - JHipster will import entities services here export default defineComponent({ name: 'Entities', setup() { provide('userService', () => new UserService()); + provide('subjectService', () => new SubjectService()); + provide('questionService', () => new QuestionService()); + provide('choiceService', () => new ChoiceService()); + provide('examAttemptService', () => new ExamAttemptService()); + provide('examAnswerService', () => new ExamAnswerService()); // jhipster-needle-add-entity-service-to-entities-component - JHipster will import entities services here }, }); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer-details.component.spec.ts b/src/main/webapp/app/entities/exam-answer/exam-answer-details.component.spec.ts new file mode 100644 index 0000000..a7cf2bd --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer-details.component.spec.ts @@ -0,0 +1,91 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ExamAnswerDetails from './exam-answer-details.vue'; + +type ExamAnswerDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const examAnswerSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('ExamAnswer Management Detail Component', () => { + let examAnswerServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + examAnswerServiceStub = { + find: vi.fn(), + }; + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + examAnswerService: () => examAnswerServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + examAnswerServiceStub.find.mockResolvedValue(examAnswerSample); + route = { + params: { + examAnswerId: `${123}`, + }, + }; + const wrapper = shallowMount(ExamAnswerDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.examAnswer).toMatchObject(examAnswerSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + examAnswerServiceStub.find.mockResolvedValue(examAnswerSample); + const wrapper = shallowMount(ExamAnswerDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer-details.component.ts b/src/main/webapp/app/entities/exam-answer/exam-answer-details.component.ts new file mode 100644 index 0000000..0e235f4 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer-details.component.ts @@ -0,0 +1,42 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type IExamAnswer } from '@/shared/model/exam-answer.model'; + +import ExamAnswerService from './exam-answer.service'; + +export default defineComponent({ + name: 'ExamAnswerDetails', + setup() { + const examAnswerService = inject('examAnswerService', () => new ExamAnswerService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const examAnswer: Ref = ref({}); + + const retrieveExamAnswer = async examAnswerId => { + try { + const res = await examAnswerService().find(examAnswerId); + examAnswer.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.examAnswerId) { + retrieveExamAnswer(route.params.examAnswerId); + } + + return { + examAnswer, + + previousState, + t$: useI18n().t, + }; + }, +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer-details.vue b/src/main/webapp/app/entities/exam-answer/exam-answer-details.vue new file mode 100644 index 0000000..1dab3f5 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer-details.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer-update.component.spec.ts b/src/main/webapp/app/entities/exam-answer/exam-answer-update.component.spec.ts new file mode 100644 index 0000000..247bf29 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer-update.component.spec.ts @@ -0,0 +1,142 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ExamAnswerUpdate from './exam-answer-update.vue'; + +type ExamAnswerUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const examAnswerSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('ExamAnswer Management Update Component', () => { + let comp: ExamAnswerUpdateComponentType; + let examAnswerServiceStub: any; + + beforeEach(() => { + route = {}; + examAnswerServiceStub = { + retrieve: vi.fn(), + find: vi.fn(), + update: vi.fn(), + create: vi.fn(), + }; + examAnswerServiceStub.retrieve.mockResolvedValueOnce([]); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + examAnswerService: () => examAnswerServiceStub, + questionService: () => ({ + retrieve: vi.fn().mockResolvedValue({}), + }), + examAttemptService: () => ({ + retrieve: vi.fn().mockResolvedValue({}), + }), + }, + }; + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(ExamAnswerUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.examAnswer = examAnswerSample; + examAnswerServiceStub.update.mockResolvedValue(examAnswerSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(examAnswerServiceStub.update).toHaveBeenCalledWith(examAnswerSample); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + examAnswerServiceStub.create.mockResolvedValue(entity); + const wrapper = shallowMount(ExamAnswerUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.examAnswer = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(examAnswerServiceStub.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + examAnswerServiceStub.find.mockResolvedValue(examAnswerSample); + examAnswerServiceStub.retrieve.mockResolvedValue([examAnswerSample]); + + // WHEN + route = { + params: { + examAnswerId: `${examAnswerSample.id}`, + }, + }; + const wrapper = shallowMount(ExamAnswerUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.examAnswer).toMatchObject(examAnswerSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + examAnswerServiceStub.find.mockResolvedValue(examAnswerSample); + const wrapper = shallowMount(ExamAnswerUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer-update.component.ts b/src/main/webapp/app/entities/exam-answer/exam-answer-update.component.ts new file mode 100644 index 0000000..baa5e57 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer-update.component.ts @@ -0,0 +1,144 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useVuelidate } from '@vuelidate/core'; + +import ExamAttemptService from '@/entities/exam-attempt/exam-attempt.service'; +import QuestionService from '@/entities/question/question.service'; +import { useAlertService } from '@/shared/alert/alert.service'; +import { useValidation } from '@/shared/composables'; +import { OptionKey } from '@/shared/model/enumerations/option-key.model'; +import { ExamAnswer, type IExamAnswer } from '@/shared/model/exam-answer.model'; +import { type IExamAttempt } from '@/shared/model/exam-attempt.model'; +import { type IQuestion } from '@/shared/model/question.model'; + +import ExamAnswerService from './exam-answer.service'; + +export default defineComponent({ + name: 'ExamAnswerUpdate', + setup() { + const examAnswerService = inject('examAnswerService', () => new ExamAnswerService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const examAnswer: Ref = ref(new ExamAnswer()); + + const questionService = inject('questionService', () => new QuestionService()); + + const questions: Ref = ref([]); + + const examAttemptService = inject('examAttemptService', () => new ExamAttemptService()); + + const examAttempts: Ref = ref([]); + const optionKeyValues: Ref = ref(Object.keys(OptionKey)); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveExamAnswer = async examAnswerId => { + try { + const res = await examAnswerService().find(examAnswerId); + examAnswer.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.examAnswerId) { + retrieveExamAnswer(route.params.examAnswerId); + } + + const initRelationships = () => { + questionService() + .retrieve() + .then(res => { + questions.value = res.data; + }); + examAttemptService() + .retrieve() + .then(res => { + examAttempts.value = res.data; + }); + }; + + initRelationships(); + + const { t: t$ } = useI18n(); + const validations = useValidation(); + const validationRules = { + questionTextSnapshot: { + required: validations.required(t$('entity.validation.required').toString()), + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 2000 }).toString(), 2000), + }, + explanationSnapshot: { + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 2000 }).toString(), 2000), + }, + selectedOption: {}, + selectedContentSnapshot: { + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 500 }).toString(), 500), + }, + correct: {}, + awardedPoints: { + integer: validations.integer(t$('entity.validation.number').toString()), + min: validations.minValue(t$('entity.validation.min', { min: 0 }).toString(), 0), + }, + question: { + required: validations.required(t$('entity.validation.required').toString()), + }, + attempt: { + required: validations.required(t$('entity.validation.required').toString()), + }, + }; + const v$ = useVuelidate(validationRules, examAnswer as any); + v$.value.$validate(); + + return { + examAnswerService, + alertService, + examAnswer, + previousState, + optionKeyValues, + isSaving, + currentLanguage, + questions, + examAttempts, + v$, + t$, + }; + }, + created(): void {}, + methods: { + save(): void { + this.isSaving = true; + if (this.examAnswer.id) { + this.examAnswerService() + .update(this.examAnswer) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(this.t$('questionBankApp.examAnswer.updated', { param: param.id })); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.examAnswerService() + .create(this.examAnswer) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(this.t$('questionBankApp.examAnswer.created', { param: param.id }).toString()); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + }, +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer-update.vue b/src/main/webapp/app/entities/exam-answer/exam-answer-update.vue new file mode 100644 index 0000000..578deea --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer-update.vue @@ -0,0 +1,176 @@ + + diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer.component.spec.ts b/src/main/webapp/app/entities/exam-answer/exam-answer.component.spec.ts new file mode 100644 index 0000000..9d77970 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer.component.spec.ts @@ -0,0 +1,103 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ExamAnswer from './exam-answer.vue'; + +type ExamAnswerComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('ExamAnswer Management Component', () => { + let examAnswerServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + examAnswerServiceStub = { + retrieve: vi.fn(), + delete: vi.fn(), + }; + examAnswerServiceStub.retrieve.mockResolvedValue({ headers: {} }); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + examAnswerService: () => examAnswerServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + examAnswerServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(ExamAnswer, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(examAnswerServiceStub.retrieve).toHaveBeenCalledOnce(); + expect(comp.examAnswers[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + }); + describe('Handles', () => { + let comp: ExamAnswerComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(ExamAnswer, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + examAnswerServiceStub.retrieve.mockReset(); + examAnswerServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [] }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + examAnswerServiceStub.delete.mockResolvedValue({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeExamAnswer(); + await comp.$nextTick(); // clear components + + // THEN + expect(examAnswerServiceStub.delete).toHaveBeenCalled(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(examAnswerServiceStub.retrieve).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer.component.ts b/src/main/webapp/app/entities/exam-answer/exam-answer.component.ts new file mode 100644 index 0000000..8f2b5aa --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer.component.ts @@ -0,0 +1,78 @@ +import { type Ref, defineComponent, inject, onMounted, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type IExamAnswer } from '@/shared/model/exam-answer.model'; + +import ExamAnswerService from './exam-answer.service'; + +export default defineComponent({ + name: 'ExamAnswer', + setup() { + const { t: t$ } = useI18n(); + const examAnswerService = inject('examAnswerService', () => new ExamAnswerService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const examAnswers: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => {}; + + const retrieveExamAnswers = async () => { + isFetching.value = true; + try { + const res = await examAnswerService().retrieve(); + examAnswers.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveExamAnswers(); + }; + + onMounted(async () => { + await retrieveExamAnswers(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: IExamAnswer) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeExamAnswer = async () => { + try { + await examAnswerService().delete(removeId.value); + const message = t$('questionBankApp.examAnswer.deleted', { param: removeId.value }).toString(); + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveExamAnswers(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + return { + examAnswers, + handleSyncList, + isFetching, + retrieveExamAnswers, + clear, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeExamAnswer, + t$, + }; + }, +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer.service.spec.ts b/src/main/webapp/app/entities/exam-answer/exam-answer.service.spec.ts new file mode 100644 index 0000000..66203e6 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer.service.spec.ts @@ -0,0 +1,177 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import axios from 'axios'; + +import { ExamAnswer } from '@/shared/model/exam-answer.model'; + +import ExamAnswerService from './exam-answer.service'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: vi.spyOn(axios, 'get'), + post: vi.spyOn(axios, 'post'), + put: vi.spyOn(axios, 'put'), + patch: vi.spyOn(axios, 'patch'), + delete: vi.spyOn(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('ExamAnswer Service', () => { + let service: ExamAnswerService; + let elemDefault; + + beforeEach(() => { + service = new ExamAnswerService(); + elemDefault = new ExamAnswer(123, 'AAAAAAA', 'AAAAAAA', 'A', 'AAAAAAA', false, 0); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { ...elemDefault }; + axiosStub.get.mockResolvedValue({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.mockRejectedValue(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a ExamAnswer', async () => { + const returnedFromService = { id: 123, ...elemDefault }; + const expected = { ...returnedFromService }; + + axiosStub.post.mockResolvedValue({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a ExamAnswer', async () => { + axiosStub.post.mockRejectedValue(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a ExamAnswer', async () => { + const returnedFromService = { + questionTextSnapshot: 'BBBBBB', + explanationSnapshot: 'BBBBBB', + selectedOption: 'BBBBBB', + selectedContentSnapshot: 'BBBBBB', + correct: true, + awardedPoints: 1, + ...elemDefault, + }; + + const expected = { ...returnedFromService }; + axiosStub.put.mockResolvedValue({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a ExamAnswer', async () => { + axiosStub.put.mockRejectedValue(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a ExamAnswer', async () => { + const patchObject = { questionTextSnapshot: 'BBBBBB', explanationSnapshot: 'BBBBBB', ...new ExamAnswer() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { ...returnedFromService }; + axiosStub.patch.mockResolvedValue({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a ExamAnswer', async () => { + axiosStub.patch.mockRejectedValue(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of ExamAnswer', async () => { + const returnedFromService = { + questionTextSnapshot: 'BBBBBB', + explanationSnapshot: 'BBBBBB', + selectedOption: 'BBBBBB', + selectedContentSnapshot: 'BBBBBB', + correct: true, + awardedPoints: 1, + ...elemDefault, + }; + const expected = { ...returnedFromService }; + axiosStub.get.mockResolvedValue([returnedFromService]); + return service.retrieve().then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of ExamAnswer', async () => { + axiosStub.get.mockRejectedValue(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a ExamAnswer', async () => { + axiosStub.delete.mockResolvedValue({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a ExamAnswer', async () => { + axiosStub.delete.mockRejectedValue(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer.service.ts b/src/main/webapp/app/entities/exam-answer/exam-answer.service.ts new file mode 100644 index 0000000..2057ae8 --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer.service.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; + +import { type IExamAnswer } from '@/shared/model/exam-answer.model'; + +const baseApiUrl = 'api/exam-answers'; + +export default class ExamAnswerService { + find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + retrieve(): Promise { + return new Promise((resolve, reject) => { + axios + .get(baseApiUrl) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + create(entity: IExamAnswer): Promise { + return new Promise((resolve, reject) => { + axios + .post(baseApiUrl, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + update(entity: IExamAnswer): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + partialUpdate(entity: IExamAnswer): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/exam-answer/exam-answer.vue b/src/main/webapp/app/entities/exam-answer/exam-answer.vue new file mode 100644 index 0000000..66ea05c --- /dev/null +++ b/src/main/webapp/app/entities/exam-answer/exam-answer.vue @@ -0,0 +1,135 @@ + + + diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.component.spec.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.component.spec.ts new file mode 100644 index 0000000..852a3b9 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.component.spec.ts @@ -0,0 +1,91 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ExamAttemptDetails from './exam-attempt-details.vue'; + +type ExamAttemptDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const examAttemptSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('ExamAttempt Management Detail Component', () => { + let examAttemptServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + examAttemptServiceStub = { + find: vi.fn(), + }; + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + examAttemptService: () => examAttemptServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + examAttemptServiceStub.find.mockResolvedValue(examAttemptSample); + route = { + params: { + examAttemptId: `${123}`, + }, + }; + const wrapper = shallowMount(ExamAttemptDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.examAttempt).toMatchObject(examAttemptSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + examAttemptServiceStub.find.mockResolvedValue(examAttemptSample); + const wrapper = shallowMount(ExamAttemptDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.component.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.component.ts new file mode 100644 index 0000000..03bfc6e --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.component.ts @@ -0,0 +1,45 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { useDateFormat } from '@/shared/composables'; +import { type IExamAttempt } from '@/shared/model/exam-attempt.model'; + +import ExamAttemptService from './exam-attempt.service'; + +export default defineComponent({ + name: 'ExamAttemptDetails', + setup() { + const dateFormat = useDateFormat(); + const examAttemptService = inject('examAttemptService', () => new ExamAttemptService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const examAttempt: Ref = ref({}); + + const retrieveExamAttempt = async examAttemptId => { + try { + const res = await examAttemptService().find(examAttemptId); + examAttempt.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.examAttemptId) { + retrieveExamAttempt(route.params.examAttemptId); + } + + return { + ...dateFormat, + examAttempt, + + previousState, + t$: useI18n().t, + }; + }, +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.vue b/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.vue new file mode 100644 index 0000000..e91f179 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt-details.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.component.spec.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.component.spec.ts new file mode 100644 index 0000000..ce82c42 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.component.spec.ts @@ -0,0 +1,166 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; +import dayjs from 'dayjs'; + +import AlertService from '@/shared/alert/alert.service'; +import { DATE_TIME_LONG_FORMAT } from '@/shared/composables/date-format'; + +import ExamAttemptUpdate from './exam-attempt-update.vue'; + +type ExamAttemptUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const examAttemptSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('ExamAttempt Management Update Component', () => { + let comp: ExamAttemptUpdateComponentType; + let examAttemptServiceStub: any; + + beforeEach(() => { + route = {}; + examAttemptServiceStub = { + retrieve: vi.fn(), + find: vi.fn(), + update: vi.fn(), + create: vi.fn(), + }; + examAttemptServiceStub.retrieve.mockResolvedValueOnce([]); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + examAttemptService: () => examAttemptServiceStub, + subjectService: () => ({ + retrieve: vi.fn().mockResolvedValue({}), + }), + + userService: () => ({ + retrieve: vi.fn().mockResolvedValue({}), + }), + }, + }; + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('load', () => { + beforeEach(() => { + const wrapper = shallowMount(ExamAttemptUpdate, { global: mountOptions }); + comp = wrapper.vm; + }); + it('Should convert date from string', () => { + // GIVEN + const date = new Date('2019-10-15T11:42:02Z'); + + // WHEN + const convertedDate = comp.convertDateTimeFromServer(date); + + // THEN + expect(convertedDate).toEqual(dayjs(date).format(DATE_TIME_LONG_FORMAT)); + }); + + it('Should not convert date if date is not present', () => { + expect(comp.convertDateTimeFromServer(null)).toBeNull(); + }); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(ExamAttemptUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.examAttempt = examAttemptSample; + examAttemptServiceStub.update.mockResolvedValue(examAttemptSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(examAttemptServiceStub.update).toHaveBeenCalledWith(examAttemptSample); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + examAttemptServiceStub.create.mockResolvedValue(entity); + const wrapper = shallowMount(ExamAttemptUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.examAttempt = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(examAttemptServiceStub.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + examAttemptServiceStub.find.mockResolvedValue(examAttemptSample); + examAttemptServiceStub.retrieve.mockResolvedValue([examAttemptSample]); + + // WHEN + route = { + params: { + examAttemptId: `${examAttemptSample.id}`, + }, + }; + const wrapper = shallowMount(ExamAttemptUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.examAttempt).toMatchObject(examAttemptSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + examAttemptServiceStub.find.mockResolvedValue(examAttemptSample); + const wrapper = shallowMount(ExamAttemptUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.component.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.component.ts new file mode 100644 index 0000000..6720c2d --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.component.ts @@ -0,0 +1,140 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useVuelidate } from '@vuelidate/core'; + +import SubjectService from '@/entities/subject/subject.service'; +import UserService from '@/entities/user/user.service'; +import { useAlertService } from '@/shared/alert/alert.service'; +import { useDateFormat, useValidation } from '@/shared/composables'; +import { AttemptStatus } from '@/shared/model/enumerations/attempt-status.model'; +import { ExamAttempt, type IExamAttempt } from '@/shared/model/exam-attempt.model'; +import { type ISubject } from '@/shared/model/subject.model'; + +import ExamAttemptService from './exam-attempt.service'; + +export default defineComponent({ + name: 'ExamAttemptUpdate', + setup() { + const examAttemptService = inject('examAttemptService', () => new ExamAttemptService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const examAttempt: Ref = ref(new ExamAttempt()); + + const subjectService = inject('subjectService', () => new SubjectService()); + + const subjects: Ref = ref([]); + const userService = inject('userService', () => new UserService()); + const users: Ref> = ref([]); + const attemptStatusValues: Ref = ref(Object.keys(AttemptStatus)); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveExamAttempt = async examAttemptId => { + try { + const res = await examAttemptService().find(examAttemptId); + res.startedAt = new Date(res.startedAt); + res.submittedAt = new Date(res.submittedAt); + examAttempt.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.examAttemptId) { + retrieveExamAttempt(route.params.examAttemptId); + } + + const initRelationships = () => { + subjectService() + .retrieve() + .then(res => { + subjects.value = res.data; + }); + userService() + .retrieve() + .then(res => { + users.value = res.data; + }); + }; + + initRelationships(); + + const { t: t$ } = useI18n(); + const validations = useValidation(); + const validationRules = { + startedAt: { + required: validations.required(t$('entity.validation.required').toString()), + }, + submittedAt: {}, + status: { + required: validations.required(t$('entity.validation.required').toString()), + }, + score: { + integer: validations.integer(t$('entity.validation.number').toString()), + min: validations.minValue(t$('entity.validation.min', { min: 0 }).toString(), 0), + }, + answers: {}, + subject: { + required: validations.required(t$('entity.validation.required').toString()), + }, + user: { + required: validations.required(t$('entity.validation.required').toString()), + }, + }; + const v$ = useVuelidate(validationRules, examAttempt as any); + v$.value.$validate(); + + return { + examAttemptService, + alertService, + examAttempt, + previousState, + attemptStatusValues, + isSaving, + currentLanguage, + subjects, + users, + v$, + ...useDateFormat({ entityRef: examAttempt }), + t$, + }; + }, + created(): void {}, + methods: { + save(): void { + this.isSaving = true; + if (this.examAttempt.id) { + this.examAttemptService() + .update(this.examAttempt) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(this.t$('questionBankApp.examAttempt.updated', { param: param.id })); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.examAttemptService() + .create(this.examAttempt) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(this.t$('questionBankApp.examAttempt.created', { param: param.id }).toString()); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + }, +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.vue b/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.vue new file mode 100644 index 0000000..8ee5716 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt-update.vue @@ -0,0 +1,137 @@ + + diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt.component.spec.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt.component.spec.ts new file mode 100644 index 0000000..b081d59 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt.component.spec.ts @@ -0,0 +1,167 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import ExamAttempt from './exam-attempt.vue'; + +type ExamAttemptComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('ExamAttempt Management Component', () => { + let examAttemptServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + examAttemptServiceStub = { + retrieve: vi.fn(), + delete: vi.fn(), + }; + examAttemptServiceStub.retrieve.mockResolvedValue({ headers: {} }); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + jhiItemCount: true, + bPagination: true, + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'jhi-sort-indicator': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + examAttemptService: () => examAttemptServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + examAttemptServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(ExamAttempt, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(examAttemptServiceStub.retrieve).toHaveBeenCalledOnce(); + expect(comp.examAttempts[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should calculate the sort attribute for an id', async () => { + // WHEN + const wrapper = shallowMount(ExamAttempt, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(examAttemptServiceStub.retrieve.mock.lastCall?.[0]).toMatchObject({ + sort: ['id,asc'], + }); + }); + }); + describe('Handles', () => { + let comp: ExamAttemptComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(ExamAttempt, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + examAttemptServiceStub.retrieve.mockReset(); + examAttemptServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [] }); + }); + + it('should load a page', async () => { + // GIVEN + examAttemptServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + comp.page = 2; + await comp.$nextTick(); + + // THEN + expect(examAttemptServiceStub.retrieve).toHaveBeenCalled(); + expect(comp.examAttempts[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should not load a page if the page is the same as the previous page', () => { + // WHEN + comp.page = 1; + + // THEN + expect(examAttemptServiceStub.retrieve).not.toHaveBeenCalled(); + }); + + it('should re-initialize the page', async () => { + // GIVEN + comp.page = 2; + await comp.$nextTick(); + examAttemptServiceStub.retrieve.mockReset(); + examAttemptServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + comp.clear(); + await comp.$nextTick(); + + // THEN + expect(comp.page).toEqual(1); + expect(examAttemptServiceStub.retrieve).toHaveBeenCalledTimes(1); + expect(comp.examAttempts[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should calculate the sort attribute for a non-id attribute', async () => { + // WHEN + comp.propOrder = 'name'; + await comp.$nextTick(); + + // THEN + expect(examAttemptServiceStub.retrieve.mock.lastCall?.[0]).toMatchObject({ + sort: ['name,asc', 'id'], + }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + examAttemptServiceStub.delete.mockResolvedValue({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeExamAttempt(); + await comp.$nextTick(); // clear components + + // THEN + expect(examAttemptServiceStub.delete).toHaveBeenCalled(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(examAttemptServiceStub.retrieve).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt.component.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt.component.ts new file mode 100644 index 0000000..feaf0c9 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt.component.ts @@ -0,0 +1,137 @@ +import { type Ref, defineComponent, inject, onMounted, ref, watch } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { useDateFormat } from '@/shared/composables'; +import { type IExamAttempt } from '@/shared/model/exam-attempt.model'; + +import ExamAttemptService from './exam-attempt.service'; + +export default defineComponent({ + name: 'ExamAttempt', + setup() { + const { t: t$ } = useI18n(); + const dateFormat = useDateFormat(); + const examAttemptService = inject('examAttemptService', () => new ExamAttemptService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const itemsPerPage = ref(20); + const queryCount: Ref = ref(null); + const page: Ref = ref(1); + const propOrder = ref('id'); + const reverse = ref(false); + const totalItems = ref(0); + + const examAttempts: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => { + page.value = 1; + }; + + const sort = (): Array => { + const result = [`${propOrder.value},${reverse.value ? 'desc' : 'asc'}`]; + if (propOrder.value !== 'id') { + result.push('id'); + } + return result; + }; + + const retrieveExamAttempts = async () => { + isFetching.value = true; + try { + const paginationQuery = { + page: page.value - 1, + size: itemsPerPage.value, + sort: sort(), + }; + const res = await examAttemptService().retrieve(paginationQuery); + totalItems.value = Number(res.headers['x-total-count']); + queryCount.value = totalItems.value; + examAttempts.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveExamAttempts(); + }; + + onMounted(async () => { + await retrieveExamAttempts(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: IExamAttempt) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeExamAttempt = async () => { + try { + await examAttemptService().delete(removeId.value); + const message = t$('questionBankApp.examAttempt.deleted', { param: removeId.value }).toString(); + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveExamAttempts(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + const changeOrder = (newOrder: string) => { + if (propOrder.value === newOrder) { + reverse.value = !reverse.value; + } else { + reverse.value = false; + } + propOrder.value = newOrder; + }; + + // Whenever order changes, reset the pagination + watch([propOrder, reverse], async () => { + if (page.value === 1) { + // first page, retrieve new data + await retrieveExamAttempts(); + } else { + // reset the pagination + clear(); + } + }); + + // Whenever page changes, switch to the new page. + watch(page, async () => { + await retrieveExamAttempts(); + }); + + return { + examAttempts, + handleSyncList, + isFetching, + retrieveExamAttempts, + clear, + ...dateFormat, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeExamAttempt, + itemsPerPage, + queryCount, + page, + propOrder, + reverse, + totalItems, + changeOrder, + t$, + }; + }, +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt.service.spec.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt.service.spec.ts new file mode 100644 index 0000000..8633100 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt.service.spec.ts @@ -0,0 +1,186 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import axios from 'axios'; +import dayjs from 'dayjs'; + +import { DATE_TIME_FORMAT } from '@/shared/composables/date-format'; +import { ExamAttempt } from '@/shared/model/exam-attempt.model'; + +import ExamAttemptService from './exam-attempt.service'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: vi.spyOn(axios, 'get'), + post: vi.spyOn(axios, 'post'), + put: vi.spyOn(axios, 'put'), + patch: vi.spyOn(axios, 'patch'), + delete: vi.spyOn(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('ExamAttempt Service', () => { + let service: ExamAttemptService; + let elemDefault; + let currentDate: Date; + + beforeEach(() => { + service = new ExamAttemptService(); + currentDate = new Date(); + elemDefault = new ExamAttempt(123, currentDate, currentDate, 'IN_PROGRESS', 0); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { + startedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + submittedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + ...elemDefault, + }; + axiosStub.get.mockResolvedValue({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.mockRejectedValue(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a ExamAttempt', async () => { + const returnedFromService = { + id: 123, + startedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + submittedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + ...elemDefault, + }; + const expected = { startedAt: currentDate, submittedAt: currentDate, ...returnedFromService }; + + axiosStub.post.mockResolvedValue({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a ExamAttempt', async () => { + axiosStub.post.mockRejectedValue(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a ExamAttempt', async () => { + const returnedFromService = { + startedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + submittedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + status: 'BBBBBB', + score: 1, + ...elemDefault, + }; + + const expected = { startedAt: currentDate, submittedAt: currentDate, ...returnedFromService }; + axiosStub.put.mockResolvedValue({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a ExamAttempt', async () => { + axiosStub.put.mockRejectedValue(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a ExamAttempt', async () => { + const patchObject = { status: 'BBBBBB', score: 1, ...new ExamAttempt() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { startedAt: currentDate, submittedAt: currentDate, ...returnedFromService }; + axiosStub.patch.mockResolvedValue({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a ExamAttempt', async () => { + axiosStub.patch.mockRejectedValue(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of ExamAttempt', async () => { + const returnedFromService = { + startedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + submittedAt: dayjs(currentDate).format(DATE_TIME_FORMAT), + status: 'BBBBBB', + score: 1, + ...elemDefault, + }; + const expected = { startedAt: currentDate, submittedAt: currentDate, ...returnedFromService }; + axiosStub.get.mockResolvedValue([returnedFromService]); + return service.retrieve({ sort: {}, page: 0, size: 10 }).then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of ExamAttempt', async () => { + axiosStub.get.mockRejectedValue(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a ExamAttempt', async () => { + axiosStub.delete.mockResolvedValue({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a ExamAttempt', async () => { + axiosStub.delete.mockRejectedValue(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt.service.ts b/src/main/webapp/app/entities/exam-attempt/exam-attempt.service.ts new file mode 100644 index 0000000..744abed --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt.service.ts @@ -0,0 +1,86 @@ +import axios from 'axios'; + +import { type IExamAttempt } from '@/shared/model/exam-attempt.model'; +import buildPaginationQueryOpts from '@/shared/sort/sorts'; + +const baseApiUrl = 'api/exam-attempts'; + +export default class ExamAttemptService { + find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + retrieve(paginationQuery?: any): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}?${buildPaginationQueryOpts(paginationQuery)}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + create(entity: IExamAttempt): Promise { + return new Promise((resolve, reject) => { + axios + .post(baseApiUrl, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + update(entity: IExamAttempt): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + partialUpdate(entity: IExamAttempt): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/exam-attempt/exam-attempt.vue b/src/main/webapp/app/entities/exam-attempt/exam-attempt.vue new file mode 100644 index 0000000..c5e9c74 --- /dev/null +++ b/src/main/webapp/app/entities/exam-attempt/exam-attempt.vue @@ -0,0 +1,140 @@ + + + diff --git a/src/main/webapp/app/entities/question/question-details.component.spec.ts b/src/main/webapp/app/entities/question/question-details.component.spec.ts new file mode 100644 index 0000000..2ec68e2 --- /dev/null +++ b/src/main/webapp/app/entities/question/question-details.component.spec.ts @@ -0,0 +1,91 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import QuestionDetails from './question-details.vue'; + +type QuestionDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const questionSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('Question Management Detail Component', () => { + let questionServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + questionServiceStub = { + find: vi.fn(), + }; + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + questionService: () => questionServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + questionServiceStub.find.mockResolvedValue(questionSample); + route = { + params: { + questionId: `${123}`, + }, + }; + const wrapper = shallowMount(QuestionDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.question).toMatchObject(questionSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + questionServiceStub.find.mockResolvedValue(questionSample); + const wrapper = shallowMount(QuestionDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/question/question-details.component.ts b/src/main/webapp/app/entities/question/question-details.component.ts new file mode 100644 index 0000000..b35527f --- /dev/null +++ b/src/main/webapp/app/entities/question/question-details.component.ts @@ -0,0 +1,42 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type IQuestion } from '@/shared/model/question.model'; + +import QuestionService from './question.service'; + +export default defineComponent({ + name: 'QuestionDetails', + setup() { + const questionService = inject('questionService', () => new QuestionService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const question: Ref = ref({}); + + const retrieveQuestion = async questionId => { + try { + const res = await questionService().find(questionId); + question.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.questionId) { + retrieveQuestion(route.params.questionId); + } + + return { + question, + + previousState, + t$: useI18n().t, + }; + }, +}); diff --git a/src/main/webapp/app/entities/question/question-details.vue b/src/main/webapp/app/entities/question/question-details.vue new file mode 100644 index 0000000..173e3df --- /dev/null +++ b/src/main/webapp/app/entities/question/question-details.vue @@ -0,0 +1,51 @@ + + + diff --git a/src/main/webapp/app/entities/question/question-update.component.spec.ts b/src/main/webapp/app/entities/question/question-update.component.spec.ts new file mode 100644 index 0000000..b318f7d --- /dev/null +++ b/src/main/webapp/app/entities/question/question-update.component.spec.ts @@ -0,0 +1,139 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import QuestionUpdate from './question-update.vue'; + +type QuestionUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const questionSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('Question Management Update Component', () => { + let comp: QuestionUpdateComponentType; + let questionServiceStub: any; + + beforeEach(() => { + route = {}; + questionServiceStub = { + retrieve: vi.fn(), + find: vi.fn(), + update: vi.fn(), + create: vi.fn(), + }; + questionServiceStub.retrieve.mockResolvedValueOnce([]); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + questionService: () => questionServiceStub, + subjectService: () => ({ + retrieve: vi.fn().mockResolvedValue({}), + }), + }, + }; + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(QuestionUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.question = questionSample; + questionServiceStub.update.mockResolvedValue(questionSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(questionServiceStub.update).toHaveBeenCalledWith(questionSample); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + questionServiceStub.create.mockResolvedValue(entity); + const wrapper = shallowMount(QuestionUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.question = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(questionServiceStub.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + questionServiceStub.find.mockResolvedValue(questionSample); + questionServiceStub.retrieve.mockResolvedValue([questionSample]); + + // WHEN + route = { + params: { + questionId: `${questionSample.id}`, + }, + }; + const wrapper = shallowMount(QuestionUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.question).toMatchObject(questionSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + questionServiceStub.find.mockResolvedValue(questionSample); + const wrapper = shallowMount(QuestionUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/question/question-update.component.ts b/src/main/webapp/app/entities/question/question-update.component.ts new file mode 100644 index 0000000..97b4272 --- /dev/null +++ b/src/main/webapp/app/entities/question/question-update.component.ts @@ -0,0 +1,122 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useVuelidate } from '@vuelidate/core'; + +import SubjectService from '@/entities/subject/subject.service'; +import { useAlertService } from '@/shared/alert/alert.service'; +import { useValidation } from '@/shared/composables'; +import { type IQuestion, Question } from '@/shared/model/question.model'; +import { type ISubject } from '@/shared/model/subject.model'; + +import QuestionService from './question.service'; + +export default defineComponent({ + name: 'QuestionUpdate', + setup() { + const questionService = inject('questionService', () => new QuestionService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const question: Ref = ref(new Question()); + + const subjectService = inject('subjectService', () => new SubjectService()); + + const subjects: Ref = ref([]); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveQuestion = async questionId => { + try { + const res = await questionService().find(questionId); + question.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.questionId) { + retrieveQuestion(route.params.questionId); + } + + const initRelationships = () => { + subjectService() + .retrieve() + .then(res => { + subjects.value = res.data; + }); + }; + + initRelationships(); + + const { t: t$ } = useI18n(); + const validations = useValidation(); + const validationRules = { + prompt: { + required: validations.required(t$('entity.validation.required').toString()), + minLength: validations.minLength(t$('entity.validation.minlength', { min: 5 }).toString(), 5), + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 2000 }).toString(), 2000), + }, + explanation: { + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 2000 }).toString(), 2000), + }, + active: { + required: validations.required(t$('entity.validation.required').toString()), + }, + choices: {}, + subject: { + required: validations.required(t$('entity.validation.required').toString()), + }, + }; + const v$ = useVuelidate(validationRules, question as any); + v$.value.$validate(); + + return { + questionService, + alertService, + question, + previousState, + isSaving, + currentLanguage, + subjects, + v$, + t$, + }; + }, + created(): void {}, + methods: { + save(): void { + this.isSaving = true; + if (this.question.id) { + this.questionService() + .update(this.question) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(this.t$('questionBankApp.question.updated', { param: param.id })); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.questionService() + .create(this.question) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(this.t$('questionBankApp.question.created', { param: param.id }).toString()); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + }, +}); diff --git a/src/main/webapp/app/entities/question/question-update.vue b/src/main/webapp/app/entities/question/question-update.vue new file mode 100644 index 0000000..fffc5cb --- /dev/null +++ b/src/main/webapp/app/entities/question/question-update.vue @@ -0,0 +1,95 @@ + + diff --git a/src/main/webapp/app/entities/question/question.component.spec.ts b/src/main/webapp/app/entities/question/question.component.spec.ts new file mode 100644 index 0000000..8fba037 --- /dev/null +++ b/src/main/webapp/app/entities/question/question.component.spec.ts @@ -0,0 +1,167 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import Question from './question.vue'; + +type QuestionComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('Question Management Component', () => { + let questionServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + questionServiceStub = { + retrieve: vi.fn(), + delete: vi.fn(), + }; + questionServiceStub.retrieve.mockResolvedValue({ headers: {} }); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + jhiItemCount: true, + bPagination: true, + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'jhi-sort-indicator': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + questionService: () => questionServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + questionServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(Question, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(questionServiceStub.retrieve).toHaveBeenCalledOnce(); + expect(comp.questions[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should calculate the sort attribute for an id', async () => { + // WHEN + const wrapper = shallowMount(Question, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(questionServiceStub.retrieve.mock.lastCall?.[0]).toMatchObject({ + sort: ['id,asc'], + }); + }); + }); + describe('Handles', () => { + let comp: QuestionComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(Question, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + questionServiceStub.retrieve.mockReset(); + questionServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [] }); + }); + + it('should load a page', async () => { + // GIVEN + questionServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + comp.page = 2; + await comp.$nextTick(); + + // THEN + expect(questionServiceStub.retrieve).toHaveBeenCalled(); + expect(comp.questions[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should not load a page if the page is the same as the previous page', () => { + // WHEN + comp.page = 1; + + // THEN + expect(questionServiceStub.retrieve).not.toHaveBeenCalled(); + }); + + it('should re-initialize the page', async () => { + // GIVEN + comp.page = 2; + await comp.$nextTick(); + questionServiceStub.retrieve.mockReset(); + questionServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + comp.clear(); + await comp.$nextTick(); + + // THEN + expect(comp.page).toEqual(1); + expect(questionServiceStub.retrieve).toHaveBeenCalledTimes(1); + expect(comp.questions[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should calculate the sort attribute for a non-id attribute', async () => { + // WHEN + comp.propOrder = 'name'; + await comp.$nextTick(); + + // THEN + expect(questionServiceStub.retrieve.mock.lastCall?.[0]).toMatchObject({ + sort: ['name,asc', 'id'], + }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + questionServiceStub.delete.mockResolvedValue({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeQuestion(); + await comp.$nextTick(); // clear components + + // THEN + expect(questionServiceStub.delete).toHaveBeenCalled(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(questionServiceStub.retrieve).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/question/question.component.ts b/src/main/webapp/app/entities/question/question.component.ts new file mode 100644 index 0000000..445231c --- /dev/null +++ b/src/main/webapp/app/entities/question/question.component.ts @@ -0,0 +1,134 @@ +import { type Ref, defineComponent, inject, onMounted, ref, watch } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type IQuestion } from '@/shared/model/question.model'; + +import QuestionService from './question.service'; + +export default defineComponent({ + name: 'Question', + setup() { + const { t: t$ } = useI18n(); + const questionService = inject('questionService', () => new QuestionService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const itemsPerPage = ref(20); + const queryCount: Ref = ref(null); + const page: Ref = ref(1); + const propOrder = ref('id'); + const reverse = ref(false); + const totalItems = ref(0); + + const questions: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => { + page.value = 1; + }; + + const sort = (): Array => { + const result = [`${propOrder.value},${reverse.value ? 'desc' : 'asc'}`]; + if (propOrder.value !== 'id') { + result.push('id'); + } + return result; + }; + + const retrieveQuestions = async () => { + isFetching.value = true; + try { + const paginationQuery = { + page: page.value - 1, + size: itemsPerPage.value, + sort: sort(), + }; + const res = await questionService().retrieve(paginationQuery); + totalItems.value = Number(res.headers['x-total-count']); + queryCount.value = totalItems.value; + questions.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveQuestions(); + }; + + onMounted(async () => { + await retrieveQuestions(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: IQuestion) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeQuestion = async () => { + try { + await questionService().delete(removeId.value); + const message = t$('questionBankApp.question.deleted', { param: removeId.value }).toString(); + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveQuestions(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + const changeOrder = (newOrder: string) => { + if (propOrder.value === newOrder) { + reverse.value = !reverse.value; + } else { + reverse.value = false; + } + propOrder.value = newOrder; + }; + + // Whenever order changes, reset the pagination + watch([propOrder, reverse], async () => { + if (page.value === 1) { + // first page, retrieve new data + await retrieveQuestions(); + } else { + // reset the pagination + clear(); + } + }); + + // Whenever page changes, switch to the new page. + watch(page, async () => { + await retrieveQuestions(); + }); + + return { + questions, + handleSyncList, + isFetching, + retrieveQuestions, + clear, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeQuestion, + itemsPerPage, + queryCount, + page, + propOrder, + reverse, + totalItems, + changeOrder, + t$, + }; + }, +}); diff --git a/src/main/webapp/app/entities/question/question.service.spec.ts b/src/main/webapp/app/entities/question/question.service.spec.ts new file mode 100644 index 0000000..d8ddc24 --- /dev/null +++ b/src/main/webapp/app/entities/question/question.service.spec.ts @@ -0,0 +1,161 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import axios from 'axios'; + +import { Question } from '@/shared/model/question.model'; + +import QuestionService from './question.service'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: vi.spyOn(axios, 'get'), + post: vi.spyOn(axios, 'post'), + put: vi.spyOn(axios, 'put'), + patch: vi.spyOn(axios, 'patch'), + delete: vi.spyOn(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('Question Service', () => { + let service: QuestionService; + let elemDefault; + + beforeEach(() => { + service = new QuestionService(); + elemDefault = new Question(123, 'AAAAAAA', 'AAAAAAA', false); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { ...elemDefault }; + axiosStub.get.mockResolvedValue({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.mockRejectedValue(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a Question', async () => { + const returnedFromService = { id: 123, ...elemDefault }; + const expected = { ...returnedFromService }; + + axiosStub.post.mockResolvedValue({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a Question', async () => { + axiosStub.post.mockRejectedValue(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a Question', async () => { + const returnedFromService = { prompt: 'BBBBBB', explanation: 'BBBBBB', active: true, ...elemDefault }; + + const expected = { ...returnedFromService }; + axiosStub.put.mockResolvedValue({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a Question', async () => { + axiosStub.put.mockRejectedValue(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a Question', async () => { + const patchObject = { active: true, ...new Question() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { ...returnedFromService }; + axiosStub.patch.mockResolvedValue({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a Question', async () => { + axiosStub.patch.mockRejectedValue(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of Question', async () => { + const returnedFromService = { prompt: 'BBBBBB', explanation: 'BBBBBB', active: true, ...elemDefault }; + const expected = { ...returnedFromService }; + axiosStub.get.mockResolvedValue([returnedFromService]); + return service.retrieve({ sort: {}, page: 0, size: 10 }).then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of Question', async () => { + axiosStub.get.mockRejectedValue(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a Question', async () => { + axiosStub.delete.mockResolvedValue({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a Question', async () => { + axiosStub.delete.mockRejectedValue(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/question/question.service.ts b/src/main/webapp/app/entities/question/question.service.ts new file mode 100644 index 0000000..6700047 --- /dev/null +++ b/src/main/webapp/app/entities/question/question.service.ts @@ -0,0 +1,86 @@ +import axios from 'axios'; + +import { type IQuestion } from '@/shared/model/question.model'; +import buildPaginationQueryOpts from '@/shared/sort/sorts'; + +const baseApiUrl = 'api/questions'; + +export default class QuestionService { + find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + retrieve(paginationQuery?: any): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}?${buildPaginationQueryOpts(paginationQuery)}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + create(entity: IQuestion): Promise { + return new Promise((resolve, reject) => { + axios + .post(baseApiUrl, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + update(entity: IQuestion): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + partialUpdate(entity: IQuestion): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/question/question.vue b/src/main/webapp/app/entities/question/question.vue new file mode 100644 index 0000000..70a2bfc --- /dev/null +++ b/src/main/webapp/app/entities/question/question.vue @@ -0,0 +1,126 @@ + + + diff --git a/src/main/webapp/app/entities/subject/subject-details.component.spec.ts b/src/main/webapp/app/entities/subject/subject-details.component.spec.ts new file mode 100644 index 0000000..6c11256 --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject-details.component.spec.ts @@ -0,0 +1,91 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import SubjectDetails from './subject-details.vue'; + +type SubjectDetailsComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const subjectSample = { id: 123 }; + +describe('Component Tests', () => { + let alertService: AlertService; + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('Subject Management Detail Component', () => { + let subjectServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + route = {}; + subjectServiceStub = { + find: vi.fn(), + }; + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'router-link': true, + }, + provide: { + alertService, + subjectService: () => subjectServiceStub, + }, + }; + }); + + describe('Navigate to details', () => { + it('Should call load all on init', async () => { + // GIVEN + subjectServiceStub.find.mockResolvedValue(subjectSample); + route = { + params: { + subjectId: `${123}`, + }, + }; + const wrapper = shallowMount(SubjectDetails, { global: mountOptions }); + const comp = wrapper.vm; + // WHEN + await comp.$nextTick(); + + // THEN + expect(comp.subject).toMatchObject(subjectSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + subjectServiceStub.find.mockResolvedValue(subjectSample); + const wrapper = shallowMount(SubjectDetails, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/subject/subject-details.component.ts b/src/main/webapp/app/entities/subject/subject-details.component.ts new file mode 100644 index 0000000..4d9f95d --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject-details.component.ts @@ -0,0 +1,42 @@ +import { type Ref, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type ISubject } from '@/shared/model/subject.model'; + +import SubjectService from './subject.service'; + +export default defineComponent({ + name: 'SubjectDetails', + setup() { + const subjectService = inject('subjectService', () => new SubjectService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + const subject: Ref = ref({}); + + const retrieveSubject = async subjectId => { + try { + const res = await subjectService().find(subjectId); + subject.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.subjectId) { + retrieveSubject(route.params.subjectId); + } + + return { + subject, + + previousState, + t$: useI18n().t, + }; + }, +}); diff --git a/src/main/webapp/app/entities/subject/subject-details.vue b/src/main/webapp/app/entities/subject/subject-details.vue new file mode 100644 index 0000000..7f66a1c --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject-details.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/main/webapp/app/entities/subject/subject-update.component.spec.ts b/src/main/webapp/app/entities/subject/subject-update.component.spec.ts new file mode 100644 index 0000000..8a0e2a0 --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject-update.component.spec.ts @@ -0,0 +1,136 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { type RouteLocation } from 'vue-router'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import SubjectUpdate from './subject-update.vue'; + +type SubjectUpdateComponentType = InstanceType; + +let route: Partial; +const routerGoMock = vi.fn(); + +vi.mock('vue-router', () => ({ + useRoute: () => route, + useRouter: () => ({ go: routerGoMock }), +})); + +const subjectSample = { id: 123 }; + +describe('Component Tests', () => { + let mountOptions: MountingOptions['global']; + let alertService: AlertService; + + describe('Subject Management Update Component', () => { + let comp: SubjectUpdateComponentType; + let subjectServiceStub: any; + + beforeEach(() => { + route = {}; + subjectServiceStub = { + retrieve: vi.fn(), + find: vi.fn(), + update: vi.fn(), + create: vi.fn(), + }; + subjectServiceStub.retrieve.mockResolvedValueOnce([]); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + 'font-awesome-icon': true, + 'b-input-group': true, + 'b-input-group-prepend': true, + 'b-form-datepicker': true, + 'b-form-input': true, + }, + provide: { + alertService, + subjectService: () => subjectServiceStub, + }, + }; + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', async () => { + // GIVEN + const wrapper = shallowMount(SubjectUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.subject = subjectSample; + subjectServiceStub.update.mockResolvedValue(subjectSample); + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(subjectServiceStub.update).toHaveBeenCalledWith(subjectSample); + expect(comp.isSaving).toEqual(false); + }); + + it('Should call create service on save for new entity', async () => { + // GIVEN + const entity = {}; + subjectServiceStub.create.mockResolvedValue(entity); + const wrapper = shallowMount(SubjectUpdate, { global: mountOptions }); + comp = wrapper.vm; + comp.subject = entity; + + // WHEN + comp.save(); + await comp.$nextTick(); + + // THEN + expect(subjectServiceStub.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }); + }); + + describe('Before route enter', () => { + it('Should retrieve data', async () => { + // GIVEN + subjectServiceStub.find.mockResolvedValue(subjectSample); + subjectServiceStub.retrieve.mockResolvedValue([subjectSample]); + + // WHEN + route = { + params: { + subjectId: `${subjectSample.id}`, + }, + }; + const wrapper = shallowMount(SubjectUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(comp.subject).toMatchObject(subjectSample); + }); + }); + + describe('Previous state', () => { + it('Should go previous state', async () => { + subjectServiceStub.find.mockResolvedValue(subjectSample); + const wrapper = shallowMount(SubjectUpdate, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + + comp.previousState(); + await comp.$nextTick(); + + expect(routerGoMock).toHaveBeenCalledWith(-1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/subject/subject-update.component.ts b/src/main/webapp/app/entities/subject/subject-update.component.ts new file mode 100644 index 0000000..b2a4c2a --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject-update.component.ts @@ -0,0 +1,101 @@ +import { type Ref, computed, defineComponent, inject, ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useRoute, useRouter } from 'vue-router'; + +import { useVuelidate } from '@vuelidate/core'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { useValidation } from '@/shared/composables'; +import { type ISubject, Subject } from '@/shared/model/subject.model'; + +import SubjectService from './subject.service'; + +export default defineComponent({ + name: 'SubjectUpdate', + setup() { + const subjectService = inject('subjectService', () => new SubjectService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const subject: Ref = ref(new Subject()); + const isSaving = ref(false); + const currentLanguage = inject('currentLanguage', () => computed(() => navigator.language ?? 'en'), true); + + const route = useRoute(); + const router = useRouter(); + + const previousState = () => router.go(-1); + + const retrieveSubject = async subjectId => { + try { + const res = await subjectService().find(subjectId); + subject.value = res; + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + if (route.params?.subjectId) { + retrieveSubject(route.params.subjectId); + } + + const { t: t$ } = useI18n(); + const validations = useValidation(); + const validationRules = { + name: { + required: validations.required(t$('entity.validation.required').toString()), + minLength: validations.minLength(t$('entity.validation.minlength', { min: 2 }).toString(), 2), + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 100 }).toString(), 100), + }, + description: { + maxLength: validations.maxLength(t$('entity.validation.maxlength', { max: 1000 }).toString(), 1000), + }, + active: { + required: validations.required(t$('entity.validation.required').toString()), + }, + }; + const v$ = useVuelidate(validationRules, subject as any); + v$.value.$validate(); + + return { + subjectService, + alertService, + subject, + previousState, + isSaving, + currentLanguage, + v$, + t$, + }; + }, + created(): void {}, + methods: { + save(): void { + this.isSaving = true; + if (this.subject.id) { + this.subjectService() + .update(this.subject) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showInfo(this.t$('questionBankApp.subject.updated', { param: param.id })); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } else { + this.subjectService() + .create(this.subject) + .then(param => { + this.isSaving = false; + this.previousState(); + this.alertService.showSuccess(this.t$('questionBankApp.subject.created', { param: param.id }).toString()); + }) + .catch(error => { + this.isSaving = false; + this.alertService.showHttpError(error.response); + }); + } + }, + }, +}); diff --git a/src/main/webapp/app/entities/subject/subject-update.vue b/src/main/webapp/app/entities/subject/subject-update.vue new file mode 100644 index 0000000..6ba16ac --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject-update.vue @@ -0,0 +1,79 @@ + + diff --git a/src/main/webapp/app/entities/subject/subject.component.spec.ts b/src/main/webapp/app/entities/subject/subject.component.spec.ts new file mode 100644 index 0000000..aabc2db --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject.component.spec.ts @@ -0,0 +1,167 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { type MountingOptions, shallowMount } from '@vue/test-utils'; + +import AlertService from '@/shared/alert/alert.service'; + +import Subject from './subject.vue'; + +type SubjectComponentType = InstanceType; + +const bModalStub = { + render: () => {}, + methods: { + hide: () => {}, + show: () => {}, + }, +}; + +describe('Component Tests', () => { + let alertService: AlertService; + + describe('Subject Management Component', () => { + let subjectServiceStub: any; + let mountOptions: MountingOptions['global']; + + beforeEach(() => { + subjectServiceStub = { + retrieve: vi.fn(), + delete: vi.fn(), + }; + subjectServiceStub.retrieve.mockResolvedValue({ headers: {} }); + + alertService = new AlertService({ + i18n: { t: vi.fn() } as any, + toast: { + create: vi.fn(), + } as any, + }); + + mountOptions = { + stubs: { + jhiItemCount: true, + bPagination: true, + bModal: bModalStub as any, + 'font-awesome-icon': true, + 'b-badge': true, + 'jhi-sort-indicator': true, + 'b-button': true, + 'router-link': true, + }, + directives: { + 'b-modal': {}, + }, + provide: { + alertService, + subjectService: () => subjectServiceStub, + }, + }; + }); + + describe('Mount', () => { + it('Should call load all on init', async () => { + // GIVEN + subjectServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + const wrapper = shallowMount(Subject, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(subjectServiceStub.retrieve).toHaveBeenCalledOnce(); + expect(comp.subjects[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should calculate the sort attribute for an id', async () => { + // WHEN + const wrapper = shallowMount(Subject, { global: mountOptions }); + const comp = wrapper.vm; + await comp.$nextTick(); + + // THEN + expect(subjectServiceStub.retrieve.mock.lastCall?.[0]).toMatchObject({ + sort: ['id,asc'], + }); + }); + }); + describe('Handles', () => { + let comp: SubjectComponentType; + + beforeEach(async () => { + const wrapper = shallowMount(Subject, { global: mountOptions }); + comp = wrapper.vm; + await comp.$nextTick(); + subjectServiceStub.retrieve.mockReset(); + subjectServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [] }); + }); + + it('should load a page', async () => { + // GIVEN + subjectServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + comp.page = 2; + await comp.$nextTick(); + + // THEN + expect(subjectServiceStub.retrieve).toHaveBeenCalled(); + expect(comp.subjects[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should not load a page if the page is the same as the previous page', () => { + // WHEN + comp.page = 1; + + // THEN + expect(subjectServiceStub.retrieve).not.toHaveBeenCalled(); + }); + + it('should re-initialize the page', async () => { + // GIVEN + comp.page = 2; + await comp.$nextTick(); + subjectServiceStub.retrieve.mockReset(); + subjectServiceStub.retrieve.mockResolvedValue({ headers: {}, data: [{ id: 123 }] }); + + // WHEN + comp.clear(); + await comp.$nextTick(); + + // THEN + expect(comp.page).toEqual(1); + expect(subjectServiceStub.retrieve).toHaveBeenCalledTimes(1); + expect(comp.subjects[0]).toEqual(expect.objectContaining({ id: 123 })); + }); + + it('should calculate the sort attribute for a non-id attribute', async () => { + // WHEN + comp.propOrder = 'name'; + await comp.$nextTick(); + + // THEN + expect(subjectServiceStub.retrieve.mock.lastCall?.[0]).toMatchObject({ + sort: ['name,asc', 'id'], + }); + }); + + it('Should call delete service on confirmDelete', async () => { + // GIVEN + subjectServiceStub.delete.mockResolvedValue({}); + + // WHEN + comp.prepareRemove({ id: 123 }); + + comp.removeSubject(); + await comp.$nextTick(); // clear components + + // THEN + expect(subjectServiceStub.delete).toHaveBeenCalled(); + + // THEN + await comp.$nextTick(); // handle component clear watch + expect(subjectServiceStub.retrieve).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/subject/subject.component.ts b/src/main/webapp/app/entities/subject/subject.component.ts new file mode 100644 index 0000000..69426a0 --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject.component.ts @@ -0,0 +1,134 @@ +import { type Ref, defineComponent, inject, onMounted, ref, watch } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import { useAlertService } from '@/shared/alert/alert.service'; +import { type ISubject } from '@/shared/model/subject.model'; + +import SubjectService from './subject.service'; + +export default defineComponent({ + name: 'Subject', + setup() { + const { t: t$ } = useI18n(); + const subjectService = inject('subjectService', () => new SubjectService()); + const alertService = inject('alertService', () => useAlertService(), true); + + const itemsPerPage = ref(20); + const queryCount: Ref = ref(null); + const page: Ref = ref(1); + const propOrder = ref('id'); + const reverse = ref(false); + const totalItems = ref(0); + + const subjects: Ref = ref([]); + + const isFetching = ref(false); + + const clear = () => { + page.value = 1; + }; + + const sort = (): Array => { + const result = [`${propOrder.value},${reverse.value ? 'desc' : 'asc'}`]; + if (propOrder.value !== 'id') { + result.push('id'); + } + return result; + }; + + const retrieveSubjects = async () => { + isFetching.value = true; + try { + const paginationQuery = { + page: page.value - 1, + size: itemsPerPage.value, + sort: sort(), + }; + const res = await subjectService().retrieve(paginationQuery); + totalItems.value = Number(res.headers['x-total-count']); + queryCount.value = totalItems.value; + subjects.value = res.data; + } catch (err) { + alertService.showHttpError(err.response); + } finally { + isFetching.value = false; + } + }; + + const handleSyncList = () => { + retrieveSubjects(); + }; + + onMounted(async () => { + await retrieveSubjects(); + }); + + const removeId: Ref = ref(null); + const removeEntity = ref(null); + const prepareRemove = (instance: ISubject) => { + removeId.value = instance.id; + removeEntity.value.show(); + }; + const closeDialog = () => { + removeEntity.value.hide(); + }; + const removeSubject = async () => { + try { + await subjectService().delete(removeId.value); + const message = t$('questionBankApp.subject.deleted', { param: removeId.value }).toString(); + alertService.showInfo(message, { variant: 'danger' }); + removeId.value = null; + retrieveSubjects(); + closeDialog(); + } catch (error) { + alertService.showHttpError(error.response); + } + }; + + const changeOrder = (newOrder: string) => { + if (propOrder.value === newOrder) { + reverse.value = !reverse.value; + } else { + reverse.value = false; + } + propOrder.value = newOrder; + }; + + // Whenever order changes, reset the pagination + watch([propOrder, reverse], async () => { + if (page.value === 1) { + // first page, retrieve new data + await retrieveSubjects(); + } else { + // reset the pagination + clear(); + } + }); + + // Whenever page changes, switch to the new page. + watch(page, async () => { + await retrieveSubjects(); + }); + + return { + subjects, + handleSyncList, + isFetching, + retrieveSubjects, + clear, + removeId, + removeEntity, + prepareRemove, + closeDialog, + removeSubject, + itemsPerPage, + queryCount, + page, + propOrder, + reverse, + totalItems, + changeOrder, + t$, + }; + }, +}); diff --git a/src/main/webapp/app/entities/subject/subject.service.spec.ts b/src/main/webapp/app/entities/subject/subject.service.spec.ts new file mode 100644 index 0000000..6ddc924 --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject.service.spec.ts @@ -0,0 +1,161 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import axios from 'axios'; + +import { Subject } from '@/shared/model/subject.model'; + +import SubjectService from './subject.service'; + +const error = { + response: { + status: null, + data: { + type: null, + }, + }, +}; + +const axiosStub = { + get: vi.spyOn(axios, 'get'), + post: vi.spyOn(axios, 'post'), + put: vi.spyOn(axios, 'put'), + patch: vi.spyOn(axios, 'patch'), + delete: vi.spyOn(axios, 'delete'), +}; + +describe('Service Tests', () => { + describe('Subject Service', () => { + let service: SubjectService; + let elemDefault; + + beforeEach(() => { + service = new SubjectService(); + elemDefault = new Subject(123, 'AAAAAAA', 'AAAAAAA', false); + }); + + describe('Service methods', () => { + it('should find an element', async () => { + const returnedFromService = { ...elemDefault }; + axiosStub.get.mockResolvedValue({ data: returnedFromService }); + + return service.find(123).then(res => { + expect(res).toMatchObject(elemDefault); + }); + }); + + it('should not find an element', async () => { + axiosStub.get.mockRejectedValue(error); + return service + .find(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should create a Subject', async () => { + const returnedFromService = { id: 123, ...elemDefault }; + const expected = { ...returnedFromService }; + + axiosStub.post.mockResolvedValue({ data: returnedFromService }); + return service.create({}).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not create a Subject', async () => { + axiosStub.post.mockRejectedValue(error); + + return service + .create({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should update a Subject', async () => { + const returnedFromService = { name: 'BBBBBB', description: 'BBBBBB', active: true, ...elemDefault }; + + const expected = { ...returnedFromService }; + axiosStub.put.mockResolvedValue({ data: returnedFromService }); + + return service.update(expected).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not update a Subject', async () => { + axiosStub.put.mockRejectedValue(error); + + return service + .update({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should partial update a Subject', async () => { + const patchObject = { name: 'BBBBBB', ...new Subject() }; + const returnedFromService = Object.assign(patchObject, elemDefault); + + const expected = { ...returnedFromService }; + axiosStub.patch.mockResolvedValue({ data: returnedFromService }); + + return service.partialUpdate(patchObject).then(res => { + expect(res).toMatchObject(expected); + }); + }); + + it('should not partial update a Subject', async () => { + axiosStub.patch.mockRejectedValue(error); + + return service + .partialUpdate({}) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should return a list of Subject', async () => { + const returnedFromService = { name: 'BBBBBB', description: 'BBBBBB', active: true, ...elemDefault }; + const expected = { ...returnedFromService }; + axiosStub.get.mockResolvedValue([returnedFromService]); + return service.retrieve({ sort: {}, page: 0, size: 10 }).then(res => { + expect(res).toContainEqual(expected); + }); + }); + + it('should not return a list of Subject', async () => { + axiosStub.get.mockRejectedValue(error); + + return service + .retrieve() + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + + it('should delete a Subject', async () => { + axiosStub.delete.mockResolvedValue({ ok: true }); + return service.delete(123).then(res => { + expect(res.ok).toBeTruthy(); + }); + }); + + it('should not delete a Subject', async () => { + axiosStub.delete.mockRejectedValue(error); + + return service + .delete(123) + .then() + .catch(err => { + expect(err).toMatchObject(error); + }); + }); + }); + }); +}); diff --git a/src/main/webapp/app/entities/subject/subject.service.ts b/src/main/webapp/app/entities/subject/subject.service.ts new file mode 100644 index 0000000..d0884af --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject.service.ts @@ -0,0 +1,86 @@ +import axios from 'axios'; + +import { type ISubject } from '@/shared/model/subject.model'; +import buildPaginationQueryOpts from '@/shared/sort/sorts'; + +const baseApiUrl = 'api/subjects'; + +export default class SubjectService { + find(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + retrieve(paginationQuery?: any): Promise { + return new Promise((resolve, reject) => { + axios + .get(`${baseApiUrl}?${buildPaginationQueryOpts(paginationQuery)}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + delete(id: number): Promise { + return new Promise((resolve, reject) => { + axios + .delete(`${baseApiUrl}/${id}`) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + create(entity: ISubject): Promise { + return new Promise((resolve, reject) => { + axios + .post(baseApiUrl, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + update(entity: ISubject): Promise { + return new Promise((resolve, reject) => { + axios + .put(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } + + partialUpdate(entity: ISubject): Promise { + return new Promise((resolve, reject) => { + axios + .patch(`${baseApiUrl}/${entity.id}`, entity) + .then(res => { + resolve(res.data); + }) + .catch(err => { + reject(err); + }); + }); + } +} diff --git a/src/main/webapp/app/entities/subject/subject.vue b/src/main/webapp/app/entities/subject/subject.vue new file mode 100644 index 0000000..af748d0 --- /dev/null +++ b/src/main/webapp/app/entities/subject/subject.vue @@ -0,0 +1,115 @@ + + + diff --git a/src/main/webapp/app/router/entities.ts b/src/main/webapp/app/router/entities.ts index 451fe99..012905a 100644 --- a/src/main/webapp/app/router/entities.ts +++ b/src/main/webapp/app/router/entities.ts @@ -1,11 +1,152 @@ +import { Authority } from '@/shared/jhipster/constants'; const Entities = () => import('@/entities/entities.vue'); +const Subject = () => import('@/entities/subject/subject.vue'); +const SubjectUpdate = () => import('@/entities/subject/subject-update.vue'); +const SubjectDetails = () => import('@/entities/subject/subject-details.vue'); + +const Question = () => import('@/entities/question/question.vue'); +const QuestionUpdate = () => import('@/entities/question/question-update.vue'); +const QuestionDetails = () => import('@/entities/question/question-details.vue'); + +const Choice = () => import('@/entities/choice/choice.vue'); +const ChoiceUpdate = () => import('@/entities/choice/choice-update.vue'); +const ChoiceDetails = () => import('@/entities/choice/choice-details.vue'); + +const ExamAttempt = () => import('@/entities/exam-attempt/exam-attempt.vue'); +const ExamAttemptUpdate = () => import('@/entities/exam-attempt/exam-attempt-update.vue'); +const ExamAttemptDetails = () => import('@/entities/exam-attempt/exam-attempt-details.vue'); + +const ExamAnswer = () => import('@/entities/exam-answer/exam-answer.vue'); +const ExamAnswerUpdate = () => import('@/entities/exam-answer/exam-answer-update.vue'); +const ExamAnswerDetails = () => import('@/entities/exam-answer/exam-answer-details.vue'); + // jhipster-needle-add-entity-to-router-import - JHipster will import entities to the router here export default { path: '/', component: Entities, children: [ + { + path: 'subject', + name: 'Subject', + component: Subject, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'subject/new', + name: 'SubjectCreate', + component: SubjectUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'subject/:subjectId/edit', + name: 'SubjectEdit', + component: SubjectUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'subject/:subjectId/view', + name: 'SubjectView', + component: SubjectDetails, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'question', + name: 'Question', + component: Question, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'question/new', + name: 'QuestionCreate', + component: QuestionUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'question/:questionId/edit', + name: 'QuestionEdit', + component: QuestionUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'question/:questionId/view', + name: 'QuestionView', + component: QuestionDetails, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'choice', + name: 'Choice', + component: Choice, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'choice/new', + name: 'ChoiceCreate', + component: ChoiceUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'choice/:choiceId/edit', + name: 'ChoiceEdit', + component: ChoiceUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'choice/:choiceId/view', + name: 'ChoiceView', + component: ChoiceDetails, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-attempt', + name: 'ExamAttempt', + component: ExamAttempt, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-attempt/new', + name: 'ExamAttemptCreate', + component: ExamAttemptUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-attempt/:examAttemptId/edit', + name: 'ExamAttemptEdit', + component: ExamAttemptUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-attempt/:examAttemptId/view', + name: 'ExamAttemptView', + component: ExamAttemptDetails, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-answer', + name: 'ExamAnswer', + component: ExamAnswer, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-answer/new', + name: 'ExamAnswerCreate', + component: ExamAnswerUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-answer/:examAnswerId/edit', + name: 'ExamAnswerEdit', + component: ExamAnswerUpdate, + meta: { authorities: [Authority.USER] }, + }, + { + path: 'exam-answer/:examAnswerId/view', + name: 'ExamAnswerView', + component: ExamAnswerDetails, + meta: { authorities: [Authority.USER] }, + }, // jhipster-needle-add-entity-to-router - JHipster will add entities to the router here ], }; diff --git a/src/main/webapp/app/shared/model/choice.model.ts b/src/main/webapp/app/shared/model/choice.model.ts new file mode 100644 index 0000000..4e52f48 --- /dev/null +++ b/src/main/webapp/app/shared/model/choice.model.ts @@ -0,0 +1,24 @@ +import { type OptionKey } from '@/shared/model/enumerations/option-key.model'; +import { type IQuestion } from '@/shared/model/question.model'; + +export interface IChoice { + id?: number; + optionKey?: keyof typeof OptionKey; + content?: string; + displayOrder?: number; + correct?: boolean; + question?: IQuestion; +} + +export class Choice implements IChoice { + constructor( + public id?: number, + public optionKey?: keyof typeof OptionKey, + public content?: string, + public displayOrder?: number, + public correct?: boolean, + public question?: IQuestion, + ) { + this.correct = this.correct ?? false; + } +} diff --git a/src/main/webapp/app/shared/model/enumerations/attempt-status.model.ts b/src/main/webapp/app/shared/model/enumerations/attempt-status.model.ts new file mode 100644 index 0000000..d56d18e --- /dev/null +++ b/src/main/webapp/app/shared/model/enumerations/attempt-status.model.ts @@ -0,0 +1,5 @@ +export enum AttemptStatus { + IN_PROGRESS = 'IN_PROGRESS', + + SUBMITTED = 'SUBMITTED', +} diff --git a/src/main/webapp/app/shared/model/enumerations/option-key.model.ts b/src/main/webapp/app/shared/model/enumerations/option-key.model.ts new file mode 100644 index 0000000..48442ac --- /dev/null +++ b/src/main/webapp/app/shared/model/enumerations/option-key.model.ts @@ -0,0 +1,9 @@ +export enum OptionKey { + A = 'A', + + B = 'B', + + C = 'C', + + D = 'D', +} diff --git a/src/main/webapp/app/shared/model/exam-answer.model.ts b/src/main/webapp/app/shared/model/exam-answer.model.ts new file mode 100644 index 0000000..da313f0 --- /dev/null +++ b/src/main/webapp/app/shared/model/exam-answer.model.ts @@ -0,0 +1,31 @@ +import { type OptionKey } from '@/shared/model/enumerations/option-key.model'; +import { type IExamAttempt } from '@/shared/model/exam-attempt.model'; +import { type IQuestion } from '@/shared/model/question.model'; + +export interface IExamAnswer { + id?: number; + questionTextSnapshot?: string; + explanationSnapshot?: string | null; + selectedOption?: keyof typeof OptionKey | null; + selectedContentSnapshot?: string | null; + correct?: boolean | null; + awardedPoints?: number | null; + question?: IQuestion; + attempt?: IExamAttempt; +} + +export class ExamAnswer implements IExamAnswer { + constructor( + public id?: number, + public questionTextSnapshot?: string, + public explanationSnapshot?: string | null, + public selectedOption?: keyof typeof OptionKey | null, + public selectedContentSnapshot?: string | null, + public correct?: boolean | null, + public awardedPoints?: number | null, + public question?: IQuestion, + public attempt?: IExamAttempt, + ) { + this.correct = this.correct ?? false; + } +} diff --git a/src/main/webapp/app/shared/model/exam-attempt.model.ts b/src/main/webapp/app/shared/model/exam-attempt.model.ts new file mode 100644 index 0000000..73a228e --- /dev/null +++ b/src/main/webapp/app/shared/model/exam-attempt.model.ts @@ -0,0 +1,25 @@ +import { type AttemptStatus } from '@/shared/model/enumerations/attempt-status.model'; +import { type ISubject } from '@/shared/model/subject.model'; +import { type IUser } from '@/shared/model/user.model'; + +export interface IExamAttempt { + id?: number; + startedAt?: Date; + submittedAt?: Date | null; + status?: keyof typeof AttemptStatus; + score?: number | null; + subject?: ISubject; + user?: IUser; +} + +export class ExamAttempt implements IExamAttempt { + constructor( + public id?: number, + public startedAt?: Date, + public submittedAt?: Date | null, + public status?: keyof typeof AttemptStatus, + public score?: number | null, + public subject?: ISubject, + public user?: IUser, + ) {} +} diff --git a/src/main/webapp/app/shared/model/question.model.ts b/src/main/webapp/app/shared/model/question.model.ts new file mode 100644 index 0000000..db8e317 --- /dev/null +++ b/src/main/webapp/app/shared/model/question.model.ts @@ -0,0 +1,21 @@ +import { type ISubject } from '@/shared/model/subject.model'; + +export interface IQuestion { + id?: number; + prompt?: string; + explanation?: string | null; + active?: boolean; + subject?: ISubject; +} + +export class Question implements IQuestion { + constructor( + public id?: number, + public prompt?: string, + public explanation?: string | null, + public active?: boolean, + public subject?: ISubject, + ) { + this.active = this.active ?? false; + } +} diff --git a/src/main/webapp/app/shared/model/subject.model.ts b/src/main/webapp/app/shared/model/subject.model.ts new file mode 100644 index 0000000..d9e0508 --- /dev/null +++ b/src/main/webapp/app/shared/model/subject.model.ts @@ -0,0 +1,17 @@ +export interface ISubject { + id?: number; + name?: string; + description?: string | null; + active?: boolean; +} + +export class Subject implements ISubject { + constructor( + public id?: number, + public name?: string, + public description?: string | null, + public active?: boolean, + ) { + this.active = this.active ?? false; + } +} diff --git a/src/main/webapp/i18n/en/attemptStatus.json b/src/main/webapp/i18n/en/attemptStatus.json new file mode 100644 index 0000000..02e356d --- /dev/null +++ b/src/main/webapp/i18n/en/attemptStatus.json @@ -0,0 +1,9 @@ +{ + "questionBankApp": { + "AttemptStatus": { + "null": "", + "IN_PROGRESS": "IN_PROGRESS", + "SUBMITTED": "SUBMITTED" + } + } +} diff --git a/src/main/webapp/i18n/en/choice.json b/src/main/webapp/i18n/en/choice.json new file mode 100644 index 0000000..2c2da3a --- /dev/null +++ b/src/main/webapp/i18n/en/choice.json @@ -0,0 +1,28 @@ +{ + "questionBankApp": { + "choice": { + "home": { + "title": "Choices", + "refreshListLabel": "Refresh list", + "createLabel": "Create a new Choice", + "createOrEditLabel": "Create or edit a Choice", + "notFound": "No Choices found" + }, + "created": "A new Choice is created with identifier { param }", + "updated": "A Choice is updated with identifier { param }", + "deleted": "A Choice is deleted with identifier { param }", + "delete": { + "question": "Are you sure you want to delete Choice { id }?" + }, + "detail": { + "title": "Choice" + }, + "id": "ID", + "optionKey": "Option Key", + "content": "Content", + "displayOrder": "Display Order", + "correct": "Correct", + "question": "Question" + } + } +} diff --git a/src/main/webapp/i18n/en/examAnswer.json b/src/main/webapp/i18n/en/examAnswer.json new file mode 100644 index 0000000..ec71c61 --- /dev/null +++ b/src/main/webapp/i18n/en/examAnswer.json @@ -0,0 +1,31 @@ +{ + "questionBankApp": { + "examAnswer": { + "home": { + "title": "Exam Answers", + "refreshListLabel": "Refresh list", + "createLabel": "Create a new Exam Answer", + "createOrEditLabel": "Create or edit a Exam Answer", + "notFound": "No Exam Answers found" + }, + "created": "A new Exam Answer is created with identifier { param }", + "updated": "A Exam Answer is updated with identifier { param }", + "deleted": "A Exam Answer is deleted with identifier { param }", + "delete": { + "question": "Are you sure you want to delete Exam Answer { id }?" + }, + "detail": { + "title": "Exam Answer" + }, + "id": "ID", + "questionTextSnapshot": "Question Text Snapshot", + "explanationSnapshot": "Explanation Snapshot", + "selectedOption": "Selected Option", + "selectedContentSnapshot": "Selected Content Snapshot", + "correct": "Correct", + "awardedPoints": "Awarded Points", + "question": "Question", + "attempt": "Attempt" + } + } +} diff --git a/src/main/webapp/i18n/en/examAttempt.json b/src/main/webapp/i18n/en/examAttempt.json new file mode 100644 index 0000000..5cb3d62 --- /dev/null +++ b/src/main/webapp/i18n/en/examAttempt.json @@ -0,0 +1,30 @@ +{ + "questionBankApp": { + "examAttempt": { + "home": { + "title": "Exam Attempts", + "refreshListLabel": "Refresh list", + "createLabel": "Create a new Exam Attempt", + "createOrEditLabel": "Create or edit a Exam Attempt", + "notFound": "No Exam Attempts found" + }, + "created": "A new Exam Attempt is created with identifier { param }", + "updated": "A Exam Attempt is updated with identifier { param }", + "deleted": "A Exam Attempt is deleted with identifier { param }", + "delete": { + "question": "Are you sure you want to delete Exam Attempt { id }?" + }, + "detail": { + "title": "Exam Attempt" + }, + "id": "ID", + "startedAt": "Started At", + "submittedAt": "Submitted At", + "status": "Status", + "score": "Score", + "answer": "Answer", + "subject": "Subject", + "user": "User" + } + } +} diff --git a/src/main/webapp/i18n/en/global.json b/src/main/webapp/i18n/en/global.json index cba121e..e81a956 100644 --- a/src/main/webapp/i18n/en/global.json +++ b/src/main/webapp/i18n/en/global.json @@ -7,7 +7,12 @@ "jhipster-needle-menu-add-element": "JHipster will add additional menu entries here (do not translate!)", "entities": { "main": "Entities", - "jhipster-needle-menu-add-entry": "JHipster will add additional entities here (do not translate!)" + "jhipster-needle-menu-add-entry": "JHipster will add additional entities here (do not translate!)", + "subject": "Subject", + "question": "Question", + "choice": "Choice", + "examAttempt": "Exam Attempt", + "examAnswer": "Exam Answer" }, "account": { "main": "Account", diff --git a/src/main/webapp/i18n/en/optionKey.json b/src/main/webapp/i18n/en/optionKey.json new file mode 100644 index 0000000..159026c --- /dev/null +++ b/src/main/webapp/i18n/en/optionKey.json @@ -0,0 +1,11 @@ +{ + "questionBankApp": { + "OptionKey": { + "null": "", + "A": "A", + "B": "B", + "C": "C", + "D": "D" + } + } +} diff --git a/src/main/webapp/i18n/en/question.json b/src/main/webapp/i18n/en/question.json new file mode 100644 index 0000000..97b1915 --- /dev/null +++ b/src/main/webapp/i18n/en/question.json @@ -0,0 +1,28 @@ +{ + "questionBankApp": { + "question": { + "home": { + "title": "Questions", + "refreshListLabel": "Refresh list", + "createLabel": "Create a new Question", + "createOrEditLabel": "Create or edit a Question", + "notFound": "No Questions found" + }, + "created": "A new Question is created with identifier { param }", + "updated": "A Question is updated with identifier { param }", + "deleted": "A Question is deleted with identifier { param }", + "delete": { + "question": "Are you sure you want to delete Question { id }?" + }, + "detail": { + "title": "Question" + }, + "id": "ID", + "prompt": "Prompt", + "explanation": "Explanation", + "active": "Active", + "choice": "Choice", + "subject": "Subject" + } + } +} diff --git a/src/main/webapp/i18n/en/subject.json b/src/main/webapp/i18n/en/subject.json new file mode 100644 index 0000000..11fa0e6 --- /dev/null +++ b/src/main/webapp/i18n/en/subject.json @@ -0,0 +1,26 @@ +{ + "questionBankApp": { + "subject": { + "home": { + "title": "Subjects", + "refreshListLabel": "Refresh list", + "createLabel": "Create a new Subject", + "createOrEditLabel": "Create or edit a Subject", + "notFound": "No Subjects found" + }, + "created": "A new Subject is created with identifier { param }", + "updated": "A Subject is updated with identifier { param }", + "deleted": "A Subject is deleted with identifier { param }", + "delete": { + "question": "Are you sure you want to delete Subject { id }?" + }, + "detail": { + "title": "Subject" + }, + "id": "ID", + "name": "Name", + "description": "Description", + "active": "Active" + } + } +} diff --git a/src/test/java/com/example/questionbank/domain/ChoiceAsserts.java b/src/test/java/com/example/questionbank/domain/ChoiceAsserts.java new file mode 100644 index 0000000..2b4f3b0 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ChoiceAsserts.java @@ -0,0 +1,67 @@ +package com.example.questionbank.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ChoiceAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertChoiceAllPropertiesEquals(Choice expected, Choice actual) { + assertChoiceAutoGeneratedPropertiesEquals(expected, actual); + assertChoiceAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertChoiceAllUpdatablePropertiesEquals(Choice expected, Choice actual) { + assertChoiceUpdatableFieldsEquals(expected, actual); + assertChoiceUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertChoiceAutoGeneratedPropertiesEquals(Choice expected, Choice actual) { + assertThat(actual) + .as("Verify Choice auto generated properties") + .satisfies(a -> assertThat(a.getId()).as("check id").isEqualTo(expected.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertChoiceUpdatableFieldsEquals(Choice expected, Choice actual) { + assertThat(actual) + .as("Verify Choice relevant properties") + .satisfies(a -> assertThat(a.getOptionKey()).as("check optionKey").isEqualTo(expected.getOptionKey())) + .satisfies(a -> assertThat(a.getContent()).as("check content").isEqualTo(expected.getContent())) + .satisfies(a -> assertThat(a.getDisplayOrder()).as("check displayOrder").isEqualTo(expected.getDisplayOrder())) + .satisfies(a -> assertThat(a.getCorrect()).as("check correct").isEqualTo(expected.getCorrect())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertChoiceUpdatableRelationshipsEquals(Choice expected, Choice actual) { + assertThat(actual) + .as("Verify Choice relationships") + .satisfies(a -> assertThat(a.getQuestion()).as("check question").isEqualTo(expected.getQuestion())); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ChoiceTest.java b/src/test/java/com/example/questionbank/domain/ChoiceTest.java new file mode 100644 index 0000000..b4e3a6a --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ChoiceTest.java @@ -0,0 +1,37 @@ +package com.example.questionbank.domain; + +import static com.example.questionbank.domain.ChoiceTestSamples.*; +import static com.example.questionbank.domain.QuestionTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class ChoiceTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(Choice.class); + Choice choice1 = getChoiceSample1(); + Choice choice2 = new Choice(); + assertThat(choice1).isNotEqualTo(choice2); + + choice2.setId(choice1.getId()); + assertThat(choice1).isEqualTo(choice2); + + choice2 = getChoiceSample2(); + assertThat(choice1).isNotEqualTo(choice2); + } + + @Test + void questionTest() { + Choice choice = getChoiceRandomSampleGenerator(); + Question questionBack = getQuestionRandomSampleGenerator(); + + choice.setQuestion(questionBack); + assertThat(choice.getQuestion()).isEqualTo(questionBack); + + choice.question(null); + assertThat(choice.getQuestion()).isNull(); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ChoiceTestSamples.java b/src/test/java/com/example/questionbank/domain/ChoiceTestSamples.java new file mode 100644 index 0000000..d8e79d6 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ChoiceTestSamples.java @@ -0,0 +1,25 @@ +package com.example.questionbank.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class ChoiceTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + private static final AtomicInteger intCount = new AtomicInteger(random.nextInt() + 2 * Short.MAX_VALUE); + + public static Choice getChoiceSample1() { + return new Choice().id(1L).content("content1").displayOrder(1); + } + + public static Choice getChoiceSample2() { + return new Choice().id(2L).content("content2").displayOrder(2); + } + + public static Choice getChoiceRandomSampleGenerator() { + return new Choice().id(longCount.incrementAndGet()).content(UUID.randomUUID().toString()).displayOrder(intCount.incrementAndGet()); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ExamAnswerAsserts.java b/src/test/java/com/example/questionbank/domain/ExamAnswerAsserts.java new file mode 100644 index 0000000..b9f4993 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ExamAnswerAsserts.java @@ -0,0 +1,78 @@ +package com.example.questionbank.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ExamAnswerAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAnswerAllPropertiesEquals(ExamAnswer expected, ExamAnswer actual) { + assertExamAnswerAutoGeneratedPropertiesEquals(expected, actual); + assertExamAnswerAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAnswerAllUpdatablePropertiesEquals(ExamAnswer expected, ExamAnswer actual) { + assertExamAnswerUpdatableFieldsEquals(expected, actual); + assertExamAnswerUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAnswerAutoGeneratedPropertiesEquals(ExamAnswer expected, ExamAnswer actual) { + assertThat(actual) + .as("Verify ExamAnswer auto generated properties") + .satisfies(a -> assertThat(a.getId()).as("check id").isEqualTo(expected.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAnswerUpdatableFieldsEquals(ExamAnswer expected, ExamAnswer actual) { + assertThat(actual) + .as("Verify ExamAnswer relevant properties") + .satisfies(a -> + assertThat(a.getQuestionTextSnapshot()).as("check questionTextSnapshot").isEqualTo(expected.getQuestionTextSnapshot()) + ) + .satisfies(a -> + assertThat(a.getExplanationSnapshot()).as("check explanationSnapshot").isEqualTo(expected.getExplanationSnapshot()) + ) + .satisfies(a -> assertThat(a.getSelectedOption()).as("check selectedOption").isEqualTo(expected.getSelectedOption())) + .satisfies(a -> + assertThat(a.getSelectedContentSnapshot()) + .as("check selectedContentSnapshot") + .isEqualTo(expected.getSelectedContentSnapshot()) + ) + .satisfies(a -> assertThat(a.getCorrect()).as("check correct").isEqualTo(expected.getCorrect())) + .satisfies(a -> assertThat(a.getAwardedPoints()).as("check awardedPoints").isEqualTo(expected.getAwardedPoints())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAnswerUpdatableRelationshipsEquals(ExamAnswer expected, ExamAnswer actual) { + assertThat(actual) + .as("Verify ExamAnswer relationships") + .satisfies(a -> assertThat(a.getQuestion()).as("check question").isEqualTo(expected.getQuestion())) + .satisfies(a -> assertThat(a.getAttempt()).as("check attempt").isEqualTo(expected.getAttempt())); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ExamAnswerTest.java b/src/test/java/com/example/questionbank/domain/ExamAnswerTest.java new file mode 100644 index 0000000..d9d20cd --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ExamAnswerTest.java @@ -0,0 +1,50 @@ +package com.example.questionbank.domain; + +import static com.example.questionbank.domain.ExamAnswerTestSamples.*; +import static com.example.questionbank.domain.ExamAttemptTestSamples.*; +import static com.example.questionbank.domain.QuestionTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class ExamAnswerTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(ExamAnswer.class); + ExamAnswer examAnswer1 = getExamAnswerSample1(); + ExamAnswer examAnswer2 = new ExamAnswer(); + assertThat(examAnswer1).isNotEqualTo(examAnswer2); + + examAnswer2.setId(examAnswer1.getId()); + assertThat(examAnswer1).isEqualTo(examAnswer2); + + examAnswer2 = getExamAnswerSample2(); + assertThat(examAnswer1).isNotEqualTo(examAnswer2); + } + + @Test + void questionTest() { + ExamAnswer examAnswer = getExamAnswerRandomSampleGenerator(); + Question questionBack = getQuestionRandomSampleGenerator(); + + examAnswer.setQuestion(questionBack); + assertThat(examAnswer.getQuestion()).isEqualTo(questionBack); + + examAnswer.question(null); + assertThat(examAnswer.getQuestion()).isNull(); + } + + @Test + void attemptTest() { + ExamAnswer examAnswer = getExamAnswerRandomSampleGenerator(); + ExamAttempt examAttemptBack = getExamAttemptRandomSampleGenerator(); + + examAnswer.setAttempt(examAttemptBack); + assertThat(examAnswer.getAttempt()).isEqualTo(examAttemptBack); + + examAnswer.attempt(null); + assertThat(examAnswer.getAttempt()).isNull(); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ExamAnswerTestSamples.java b/src/test/java/com/example/questionbank/domain/ExamAnswerTestSamples.java new file mode 100644 index 0000000..627cc3a --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ExamAnswerTestSamples.java @@ -0,0 +1,40 @@ +package com.example.questionbank.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class ExamAnswerTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + private static final AtomicInteger intCount = new AtomicInteger(random.nextInt() + 2 * Short.MAX_VALUE); + + public static ExamAnswer getExamAnswerSample1() { + return new ExamAnswer() + .id(1L) + .questionTextSnapshot("questionTextSnapshot1") + .explanationSnapshot("explanationSnapshot1") + .selectedContentSnapshot("selectedContentSnapshot1") + .awardedPoints(1); + } + + public static ExamAnswer getExamAnswerSample2() { + return new ExamAnswer() + .id(2L) + .questionTextSnapshot("questionTextSnapshot2") + .explanationSnapshot("explanationSnapshot2") + .selectedContentSnapshot("selectedContentSnapshot2") + .awardedPoints(2); + } + + public static ExamAnswer getExamAnswerRandomSampleGenerator() { + return new ExamAnswer() + .id(longCount.incrementAndGet()) + .questionTextSnapshot(UUID.randomUUID().toString()) + .explanationSnapshot(UUID.randomUUID().toString()) + .selectedContentSnapshot(UUID.randomUUID().toString()) + .awardedPoints(intCount.incrementAndGet()); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ExamAttemptAsserts.java b/src/test/java/com/example/questionbank/domain/ExamAttemptAsserts.java new file mode 100644 index 0000000..0594ce8 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ExamAttemptAsserts.java @@ -0,0 +1,67 @@ +package com.example.questionbank.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ExamAttemptAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAttemptAllPropertiesEquals(ExamAttempt expected, ExamAttempt actual) { + assertExamAttemptAutoGeneratedPropertiesEquals(expected, actual); + assertExamAttemptAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAttemptAllUpdatablePropertiesEquals(ExamAttempt expected, ExamAttempt actual) { + assertExamAttemptUpdatableFieldsEquals(expected, actual); + assertExamAttemptUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAttemptAutoGeneratedPropertiesEquals(ExamAttempt expected, ExamAttempt actual) { + assertThat(actual) + .as("Verify ExamAttempt auto generated properties") + .satisfies(a -> assertThat(a.getId()).as("check id").isEqualTo(expected.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAttemptUpdatableFieldsEquals(ExamAttempt expected, ExamAttempt actual) { + assertThat(actual) + .as("Verify ExamAttempt relevant properties") + .satisfies(a -> assertThat(a.getStartedAt()).as("check startedAt").isEqualTo(expected.getStartedAt())) + .satisfies(a -> assertThat(a.getSubmittedAt()).as("check submittedAt").isEqualTo(expected.getSubmittedAt())) + .satisfies(a -> assertThat(a.getStatus()).as("check status").isEqualTo(expected.getStatus())) + .satisfies(a -> assertThat(a.getScore()).as("check score").isEqualTo(expected.getScore())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertExamAttemptUpdatableRelationshipsEquals(ExamAttempt expected, ExamAttempt actual) { + assertThat(actual) + .as("Verify ExamAttempt relationships") + .satisfies(a -> assertThat(a.getSubject()).as("check subject").isEqualTo(expected.getSubject())); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ExamAttemptTest.java b/src/test/java/com/example/questionbank/domain/ExamAttemptTest.java new file mode 100644 index 0000000..1bdc312 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ExamAttemptTest.java @@ -0,0 +1,62 @@ +package com.example.questionbank.domain; + +import static com.example.questionbank.domain.ExamAnswerTestSamples.*; +import static com.example.questionbank.domain.ExamAttemptTestSamples.*; +import static com.example.questionbank.domain.SubjectTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class ExamAttemptTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(ExamAttempt.class); + ExamAttempt examAttempt1 = getExamAttemptSample1(); + ExamAttempt examAttempt2 = new ExamAttempt(); + assertThat(examAttempt1).isNotEqualTo(examAttempt2); + + examAttempt2.setId(examAttempt1.getId()); + assertThat(examAttempt1).isEqualTo(examAttempt2); + + examAttempt2 = getExamAttemptSample2(); + assertThat(examAttempt1).isNotEqualTo(examAttempt2); + } + + @Test + void answerTest() { + ExamAttempt examAttempt = getExamAttemptRandomSampleGenerator(); + ExamAnswer examAnswerBack = getExamAnswerRandomSampleGenerator(); + + examAttempt.addAnswer(examAnswerBack); + assertThat(examAttempt.getAnswers()).containsOnly(examAnswerBack); + assertThat(examAnswerBack.getAttempt()).isEqualTo(examAttempt); + + examAttempt.removeAnswer(examAnswerBack); + assertThat(examAttempt.getAnswers()).doesNotContain(examAnswerBack); + assertThat(examAnswerBack.getAttempt()).isNull(); + + examAttempt.answers(new HashSet<>(Set.of(examAnswerBack))); + assertThat(examAttempt.getAnswers()).containsOnly(examAnswerBack); + assertThat(examAnswerBack.getAttempt()).isEqualTo(examAttempt); + + examAttempt.setAnswers(new HashSet<>()); + assertThat(examAttempt.getAnswers()).doesNotContain(examAnswerBack); + assertThat(examAnswerBack.getAttempt()).isNull(); + } + + @Test + void subjectTest() { + ExamAttempt examAttempt = getExamAttemptRandomSampleGenerator(); + Subject subjectBack = getSubjectRandomSampleGenerator(); + + examAttempt.setSubject(subjectBack); + assertThat(examAttempt.getSubject()).isEqualTo(subjectBack); + + examAttempt.subject(null); + assertThat(examAttempt.getSubject()).isNull(); + } +} diff --git a/src/test/java/com/example/questionbank/domain/ExamAttemptTestSamples.java b/src/test/java/com/example/questionbank/domain/ExamAttemptTestSamples.java new file mode 100644 index 0000000..fb61849 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/ExamAttemptTestSamples.java @@ -0,0 +1,24 @@ +package com.example.questionbank.domain; + +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class ExamAttemptTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + private static final AtomicInteger intCount = new AtomicInteger(random.nextInt() + 2 * Short.MAX_VALUE); + + public static ExamAttempt getExamAttemptSample1() { + return new ExamAttempt().id(1L).score(1); + } + + public static ExamAttempt getExamAttemptSample2() { + return new ExamAttempt().id(2L).score(2); + } + + public static ExamAttempt getExamAttemptRandomSampleGenerator() { + return new ExamAttempt().id(longCount.incrementAndGet()).score(intCount.incrementAndGet()); + } +} diff --git a/src/test/java/com/example/questionbank/domain/QuestionAsserts.java b/src/test/java/com/example/questionbank/domain/QuestionAsserts.java new file mode 100644 index 0000000..5f9dfc0 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/QuestionAsserts.java @@ -0,0 +1,66 @@ +package com.example.questionbank.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QuestionAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertQuestionAllPropertiesEquals(Question expected, Question actual) { + assertQuestionAutoGeneratedPropertiesEquals(expected, actual); + assertQuestionAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertQuestionAllUpdatablePropertiesEquals(Question expected, Question actual) { + assertQuestionUpdatableFieldsEquals(expected, actual); + assertQuestionUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertQuestionAutoGeneratedPropertiesEquals(Question expected, Question actual) { + assertThat(actual) + .as("Verify Question auto generated properties") + .satisfies(a -> assertThat(a.getId()).as("check id").isEqualTo(expected.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertQuestionUpdatableFieldsEquals(Question expected, Question actual) { + assertThat(actual) + .as("Verify Question relevant properties") + .satisfies(a -> assertThat(a.getPrompt()).as("check prompt").isEqualTo(expected.getPrompt())) + .satisfies(a -> assertThat(a.getExplanation()).as("check explanation").isEqualTo(expected.getExplanation())) + .satisfies(a -> assertThat(a.getActive()).as("check active").isEqualTo(expected.getActive())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertQuestionUpdatableRelationshipsEquals(Question expected, Question actual) { + assertThat(actual) + .as("Verify Question relationships") + .satisfies(a -> assertThat(a.getSubject()).as("check subject").isEqualTo(expected.getSubject())); + } +} diff --git a/src/test/java/com/example/questionbank/domain/QuestionTest.java b/src/test/java/com/example/questionbank/domain/QuestionTest.java new file mode 100644 index 0000000..eb194b6 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/QuestionTest.java @@ -0,0 +1,62 @@ +package com.example.questionbank.domain; + +import static com.example.questionbank.domain.ChoiceTestSamples.*; +import static com.example.questionbank.domain.QuestionTestSamples.*; +import static com.example.questionbank.domain.SubjectTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class QuestionTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(Question.class); + Question question1 = getQuestionSample1(); + Question question2 = new Question(); + assertThat(question1).isNotEqualTo(question2); + + question2.setId(question1.getId()); + assertThat(question1).isEqualTo(question2); + + question2 = getQuestionSample2(); + assertThat(question1).isNotEqualTo(question2); + } + + @Test + void choiceTest() { + Question question = getQuestionRandomSampleGenerator(); + Choice choiceBack = getChoiceRandomSampleGenerator(); + + question.addChoice(choiceBack); + assertThat(question.getChoices()).containsOnly(choiceBack); + assertThat(choiceBack.getQuestion()).isEqualTo(question); + + question.removeChoice(choiceBack); + assertThat(question.getChoices()).doesNotContain(choiceBack); + assertThat(choiceBack.getQuestion()).isNull(); + + question.choices(new HashSet<>(Set.of(choiceBack))); + assertThat(question.getChoices()).containsOnly(choiceBack); + assertThat(choiceBack.getQuestion()).isEqualTo(question); + + question.setChoices(new HashSet<>()); + assertThat(question.getChoices()).doesNotContain(choiceBack); + assertThat(choiceBack.getQuestion()).isNull(); + } + + @Test + void subjectTest() { + Question question = getQuestionRandomSampleGenerator(); + Subject subjectBack = getSubjectRandomSampleGenerator(); + + question.setSubject(subjectBack); + assertThat(question.getSubject()).isEqualTo(subjectBack); + + question.subject(null); + assertThat(question.getSubject()).isNull(); + } +} diff --git a/src/test/java/com/example/questionbank/domain/QuestionTestSamples.java b/src/test/java/com/example/questionbank/domain/QuestionTestSamples.java new file mode 100644 index 0000000..5226efc --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/QuestionTestSamples.java @@ -0,0 +1,26 @@ +package com.example.questionbank.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +public class QuestionTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + public static Question getQuestionSample1() { + return new Question().id(1L).prompt("prompt1").explanation("explanation1"); + } + + public static Question getQuestionSample2() { + return new Question().id(2L).prompt("prompt2").explanation("explanation2"); + } + + public static Question getQuestionRandomSampleGenerator() { + return new Question() + .id(longCount.incrementAndGet()) + .prompt(UUID.randomUUID().toString()) + .explanation(UUID.randomUUID().toString()); + } +} diff --git a/src/test/java/com/example/questionbank/domain/SubjectAsserts.java b/src/test/java/com/example/questionbank/domain/SubjectAsserts.java new file mode 100644 index 0000000..f13f1a1 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/SubjectAsserts.java @@ -0,0 +1,64 @@ +package com.example.questionbank.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SubjectAsserts { + + /** + * Asserts that the entity has all properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertSubjectAllPropertiesEquals(Subject expected, Subject actual) { + assertSubjectAutoGeneratedPropertiesEquals(expected, actual); + assertSubjectAllUpdatablePropertiesEquals(expected, actual); + } + + /** + * Asserts that the entity has all updatable properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertSubjectAllUpdatablePropertiesEquals(Subject expected, Subject actual) { + assertSubjectUpdatableFieldsEquals(expected, actual); + assertSubjectUpdatableRelationshipsEquals(expected, actual); + } + + /** + * Asserts that the entity has all the auto generated properties (fields/relationships) set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertSubjectAutoGeneratedPropertiesEquals(Subject expected, Subject actual) { + assertThat(actual) + .as("Verify Subject auto generated properties") + .satisfies(a -> assertThat(a.getId()).as("check id").isEqualTo(expected.getId())); + } + + /** + * Asserts that the entity has all the updatable fields set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertSubjectUpdatableFieldsEquals(Subject expected, Subject actual) { + assertThat(actual) + .as("Verify Subject relevant properties") + .satisfies(a -> assertThat(a.getName()).as("check name").isEqualTo(expected.getName())) + .satisfies(a -> assertThat(a.getDescription()).as("check description").isEqualTo(expected.getDescription())) + .satisfies(a -> assertThat(a.getActive()).as("check active").isEqualTo(expected.getActive())); + } + + /** + * Asserts that the entity has all the updatable relationships set. + * + * @param expected the expected entity + * @param actual the actual entity + */ + public static void assertSubjectUpdatableRelationshipsEquals(Subject expected, Subject actual) { + // empty method + } +} diff --git a/src/test/java/com/example/questionbank/domain/SubjectTest.java b/src/test/java/com/example/questionbank/domain/SubjectTest.java new file mode 100644 index 0000000..f286b7a --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/SubjectTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.domain; + +import static com.example.questionbank.domain.SubjectTestSamples.*; +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class SubjectTest { + + @Test + void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(Subject.class); + Subject subject1 = getSubjectSample1(); + Subject subject2 = new Subject(); + assertThat(subject1).isNotEqualTo(subject2); + + subject2.setId(subject1.getId()); + assertThat(subject1).isEqualTo(subject2); + + subject2 = getSubjectSample2(); + assertThat(subject1).isNotEqualTo(subject2); + } +} diff --git a/src/test/java/com/example/questionbank/domain/SubjectTestSamples.java b/src/test/java/com/example/questionbank/domain/SubjectTestSamples.java new file mode 100644 index 0000000..221d9a3 --- /dev/null +++ b/src/test/java/com/example/questionbank/domain/SubjectTestSamples.java @@ -0,0 +1,23 @@ +package com.example.questionbank.domain; + +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +public class SubjectTestSamples { + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + public static Subject getSubjectSample1() { + return new Subject().id(1L).name("name1").description("description1"); + } + + public static Subject getSubjectSample2() { + return new Subject().id(2L).name("name2").description("description2"); + } + + public static Subject getSubjectRandomSampleGenerator() { + return new Subject().id(longCount.incrementAndGet()).name(UUID.randomUUID().toString()).description(UUID.randomUUID().toString()); + } +} diff --git a/src/test/java/com/example/questionbank/service/dto/ChoiceDTOTest.java b/src/test/java/com/example/questionbank/service/dto/ChoiceDTOTest.java new file mode 100644 index 0000000..ef1f338 --- /dev/null +++ b/src/test/java/com/example/questionbank/service/dto/ChoiceDTOTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.dto; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class ChoiceDTOTest { + + @Test + void dtoEqualsVerifier() throws Exception { + TestUtil.equalsVerifier(ChoiceDTO.class); + ChoiceDTO choiceDTO1 = new ChoiceDTO(); + choiceDTO1.setId(1L); + ChoiceDTO choiceDTO2 = new ChoiceDTO(); + assertThat(choiceDTO1).isNotEqualTo(choiceDTO2); + choiceDTO2.setId(choiceDTO1.getId()); + assertThat(choiceDTO1).isEqualTo(choiceDTO2); + choiceDTO2.setId(2L); + assertThat(choiceDTO1).isNotEqualTo(choiceDTO2); + choiceDTO1.setId(null); + assertThat(choiceDTO1).isNotEqualTo(choiceDTO2); + } +} diff --git a/src/test/java/com/example/questionbank/service/dto/ExamAnswerDTOTest.java b/src/test/java/com/example/questionbank/service/dto/ExamAnswerDTOTest.java new file mode 100644 index 0000000..22c9c74 --- /dev/null +++ b/src/test/java/com/example/questionbank/service/dto/ExamAnswerDTOTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.dto; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class ExamAnswerDTOTest { + + @Test + void dtoEqualsVerifier() throws Exception { + TestUtil.equalsVerifier(ExamAnswerDTO.class); + ExamAnswerDTO examAnswerDTO1 = new ExamAnswerDTO(); + examAnswerDTO1.setId(1L); + ExamAnswerDTO examAnswerDTO2 = new ExamAnswerDTO(); + assertThat(examAnswerDTO1).isNotEqualTo(examAnswerDTO2); + examAnswerDTO2.setId(examAnswerDTO1.getId()); + assertThat(examAnswerDTO1).isEqualTo(examAnswerDTO2); + examAnswerDTO2.setId(2L); + assertThat(examAnswerDTO1).isNotEqualTo(examAnswerDTO2); + examAnswerDTO1.setId(null); + assertThat(examAnswerDTO1).isNotEqualTo(examAnswerDTO2); + } +} diff --git a/src/test/java/com/example/questionbank/service/dto/ExamAttemptDTOTest.java b/src/test/java/com/example/questionbank/service/dto/ExamAttemptDTOTest.java new file mode 100644 index 0000000..72df10f --- /dev/null +++ b/src/test/java/com/example/questionbank/service/dto/ExamAttemptDTOTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.dto; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class ExamAttemptDTOTest { + + @Test + void dtoEqualsVerifier() throws Exception { + TestUtil.equalsVerifier(ExamAttemptDTO.class); + ExamAttemptDTO examAttemptDTO1 = new ExamAttemptDTO(); + examAttemptDTO1.setId(1L); + ExamAttemptDTO examAttemptDTO2 = new ExamAttemptDTO(); + assertThat(examAttemptDTO1).isNotEqualTo(examAttemptDTO2); + examAttemptDTO2.setId(examAttemptDTO1.getId()); + assertThat(examAttemptDTO1).isEqualTo(examAttemptDTO2); + examAttemptDTO2.setId(2L); + assertThat(examAttemptDTO1).isNotEqualTo(examAttemptDTO2); + examAttemptDTO1.setId(null); + assertThat(examAttemptDTO1).isNotEqualTo(examAttemptDTO2); + } +} diff --git a/src/test/java/com/example/questionbank/service/dto/QuestionDTOTest.java b/src/test/java/com/example/questionbank/service/dto/QuestionDTOTest.java new file mode 100644 index 0000000..61ec19c --- /dev/null +++ b/src/test/java/com/example/questionbank/service/dto/QuestionDTOTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.dto; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class QuestionDTOTest { + + @Test + void dtoEqualsVerifier() throws Exception { + TestUtil.equalsVerifier(QuestionDTO.class); + QuestionDTO questionDTO1 = new QuestionDTO(); + questionDTO1.setId(1L); + QuestionDTO questionDTO2 = new QuestionDTO(); + assertThat(questionDTO1).isNotEqualTo(questionDTO2); + questionDTO2.setId(questionDTO1.getId()); + assertThat(questionDTO1).isEqualTo(questionDTO2); + questionDTO2.setId(2L); + assertThat(questionDTO1).isNotEqualTo(questionDTO2); + questionDTO1.setId(null); + assertThat(questionDTO1).isNotEqualTo(questionDTO2); + } +} diff --git a/src/test/java/com/example/questionbank/service/dto/SubjectDTOTest.java b/src/test/java/com/example/questionbank/service/dto/SubjectDTOTest.java new file mode 100644 index 0000000..bdfee6e --- /dev/null +++ b/src/test/java/com/example/questionbank/service/dto/SubjectDTOTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.dto; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.questionbank.web.rest.TestUtil; +import org.junit.jupiter.api.Test; + +class SubjectDTOTest { + + @Test + void dtoEqualsVerifier() throws Exception { + TestUtil.equalsVerifier(SubjectDTO.class); + SubjectDTO subjectDTO1 = new SubjectDTO(); + subjectDTO1.setId(1L); + SubjectDTO subjectDTO2 = new SubjectDTO(); + assertThat(subjectDTO1).isNotEqualTo(subjectDTO2); + subjectDTO2.setId(subjectDTO1.getId()); + assertThat(subjectDTO1).isEqualTo(subjectDTO2); + subjectDTO2.setId(2L); + assertThat(subjectDTO1).isNotEqualTo(subjectDTO2); + subjectDTO1.setId(null); + assertThat(subjectDTO1).isNotEqualTo(subjectDTO2); + } +} diff --git a/src/test/java/com/example/questionbank/service/mapper/ChoiceMapperTest.java b/src/test/java/com/example/questionbank/service/mapper/ChoiceMapperTest.java new file mode 100644 index 0000000..b28aafb --- /dev/null +++ b/src/test/java/com/example/questionbank/service/mapper/ChoiceMapperTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.mapper; + +import static com.example.questionbank.domain.ChoiceAsserts.*; +import static com.example.questionbank.domain.ChoiceTestSamples.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ChoiceMapperTest { + + private ChoiceMapper choiceMapper; + + @BeforeEach + void setUp() { + choiceMapper = new ChoiceMapperImpl(); + } + + @Test + void shouldConvertToDtoAndBack() { + var expected = getChoiceSample1(); + var actual = choiceMapper.toEntity(choiceMapper.toDto(expected)); + assertChoiceAllPropertiesEquals(expected, actual); + } +} diff --git a/src/test/java/com/example/questionbank/service/mapper/ExamAnswerMapperTest.java b/src/test/java/com/example/questionbank/service/mapper/ExamAnswerMapperTest.java new file mode 100644 index 0000000..822accf --- /dev/null +++ b/src/test/java/com/example/questionbank/service/mapper/ExamAnswerMapperTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.mapper; + +import static com.example.questionbank.domain.ExamAnswerAsserts.*; +import static com.example.questionbank.domain.ExamAnswerTestSamples.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ExamAnswerMapperTest { + + private ExamAnswerMapper examAnswerMapper; + + @BeforeEach + void setUp() { + examAnswerMapper = new ExamAnswerMapperImpl(); + } + + @Test + void shouldConvertToDtoAndBack() { + var expected = getExamAnswerSample1(); + var actual = examAnswerMapper.toEntity(examAnswerMapper.toDto(expected)); + assertExamAnswerAllPropertiesEquals(expected, actual); + } +} diff --git a/src/test/java/com/example/questionbank/service/mapper/ExamAttemptMapperTest.java b/src/test/java/com/example/questionbank/service/mapper/ExamAttemptMapperTest.java new file mode 100644 index 0000000..d3de2fb --- /dev/null +++ b/src/test/java/com/example/questionbank/service/mapper/ExamAttemptMapperTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.mapper; + +import static com.example.questionbank.domain.ExamAttemptAsserts.*; +import static com.example.questionbank.domain.ExamAttemptTestSamples.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ExamAttemptMapperTest { + + private ExamAttemptMapper examAttemptMapper; + + @BeforeEach + void setUp() { + examAttemptMapper = new ExamAttemptMapperImpl(); + } + + @Test + void shouldConvertToDtoAndBack() { + var expected = getExamAttemptSample1(); + var actual = examAttemptMapper.toEntity(examAttemptMapper.toDto(expected)); + assertExamAttemptAllPropertiesEquals(expected, actual); + } +} diff --git a/src/test/java/com/example/questionbank/service/mapper/QuestionMapperTest.java b/src/test/java/com/example/questionbank/service/mapper/QuestionMapperTest.java new file mode 100644 index 0000000..48873a2 --- /dev/null +++ b/src/test/java/com/example/questionbank/service/mapper/QuestionMapperTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.mapper; + +import static com.example.questionbank.domain.QuestionAsserts.*; +import static com.example.questionbank.domain.QuestionTestSamples.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class QuestionMapperTest { + + private QuestionMapper questionMapper; + + @BeforeEach + void setUp() { + questionMapper = new QuestionMapperImpl(); + } + + @Test + void shouldConvertToDtoAndBack() { + var expected = getQuestionSample1(); + var actual = questionMapper.toEntity(questionMapper.toDto(expected)); + assertQuestionAllPropertiesEquals(expected, actual); + } +} diff --git a/src/test/java/com/example/questionbank/service/mapper/SubjectMapperTest.java b/src/test/java/com/example/questionbank/service/mapper/SubjectMapperTest.java new file mode 100644 index 0000000..022ccf0 --- /dev/null +++ b/src/test/java/com/example/questionbank/service/mapper/SubjectMapperTest.java @@ -0,0 +1,24 @@ +package com.example.questionbank.service.mapper; + +import static com.example.questionbank.domain.SubjectAsserts.*; +import static com.example.questionbank.domain.SubjectTestSamples.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class SubjectMapperTest { + + private SubjectMapper subjectMapper; + + @BeforeEach + void setUp() { + subjectMapper = new SubjectMapperImpl(); + } + + @Test + void shouldConvertToDtoAndBack() { + var expected = getSubjectSample1(); + var actual = subjectMapper.toEntity(subjectMapper.toDto(expected)); + assertSubjectAllPropertiesEquals(expected, actual); + } +} diff --git a/src/test/java/com/example/questionbank/web/rest/ChoiceResourceIT.java b/src/test/java/com/example/questionbank/web/rest/ChoiceResourceIT.java new file mode 100644 index 0000000..c445b30 --- /dev/null +++ b/src/test/java/com/example/questionbank/web/rest/ChoiceResourceIT.java @@ -0,0 +1,544 @@ +package com.example.questionbank.web.rest; + +import static com.example.questionbank.domain.ChoiceAsserts.*; +import static com.example.questionbank.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.example.questionbank.IntegrationTest; +import com.example.questionbank.domain.Choice; +import com.example.questionbank.domain.Question; +import com.example.questionbank.domain.enumeration.OptionKey; +import com.example.questionbank.repository.ChoiceRepository; +import com.example.questionbank.service.dto.ChoiceDTO; +import com.example.questionbank.service.mapper.ChoiceMapper; +import jakarta.persistence.EntityManager; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.ObjectMapper; + +/** + * Integration tests for the {@link ChoiceResource} REST controller. + */ +@IntegrationTest +@AutoConfigureMockMvc +@WithMockUser +class ChoiceResourceIT { + + private static final OptionKey DEFAULT_OPTION_KEY = OptionKey.A; + private static final OptionKey UPDATED_OPTION_KEY = OptionKey.B; + + private static final String DEFAULT_CONTENT = "AAAAAAAAAA"; + private static final String UPDATED_CONTENT = "BBBBBBBBBB"; + + private static final Integer DEFAULT_DISPLAY_ORDER = 1; + private static final Integer UPDATED_DISPLAY_ORDER = 2; + + private static final Boolean DEFAULT_CORRECT = false; + private static final Boolean UPDATED_CORRECT = true; + + private static final String ENTITY_API_URL = "/api/choices"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + @Autowired + private ObjectMapper om; + + @Autowired + private ChoiceRepository choiceRepository; + + @Autowired + private ChoiceMapper choiceMapper; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restChoiceMockMvc; + + private Choice choice; + + private Choice insertedChoice; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Choice createEntity(EntityManager em) { + Choice choice = new Choice() + .optionKey(DEFAULT_OPTION_KEY) + .content(DEFAULT_CONTENT) + .displayOrder(DEFAULT_DISPLAY_ORDER) + .correct(DEFAULT_CORRECT); + // Add required entity + Question question; + if (TestUtil.findAll(em, Question.class).isEmpty()) { + question = QuestionResourceIT.createEntity(em); + em.persist(question); + em.flush(); + } else { + question = TestUtil.findAll(em, Question.class).get(0); + } + choice.setQuestion(question); + return choice; + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Choice createUpdatedEntity(EntityManager em) { + Choice updatedChoice = new Choice() + .optionKey(UPDATED_OPTION_KEY) + .content(UPDATED_CONTENT) + .displayOrder(UPDATED_DISPLAY_ORDER) + .correct(UPDATED_CORRECT); + // Add required entity + Question question; + if (TestUtil.findAll(em, Question.class).isEmpty()) { + question = QuestionResourceIT.createUpdatedEntity(em); + em.persist(question); + em.flush(); + } else { + question = TestUtil.findAll(em, Question.class).get(0); + } + updatedChoice.setQuestion(question); + return updatedChoice; + } + + @BeforeEach + void initTest() { + choice = createEntity(em); + } + + @AfterEach + void cleanup() { + if (insertedChoice != null) { + choiceRepository.delete(insertedChoice); + insertedChoice = null; + } + } + + @Test + @Transactional + void createChoice() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + var returnedChoiceDTO = om.readValue( + restChoiceMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + ChoiceDTO.class + ); + + // Validate the Choice in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + var returnedChoice = choiceMapper.toEntity(returnedChoiceDTO); + assertChoiceUpdatableFieldsEquals(returnedChoice, getPersistedChoice(returnedChoice)); + + insertedChoice = returnedChoice; + } + + @Test + @Transactional + void createChoiceWithExistingId() throws Exception { + // Create the Choice with an existing ID + choice.setId(1L); + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restChoiceMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isBadRequest()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void checkOptionKeyIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + choice.setOptionKey(null); + + // Create the Choice, which fails. + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + restChoiceMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void checkContentIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + choice.setContent(null); + + // Create the Choice, which fails. + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + restChoiceMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void checkDisplayOrderIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + choice.setDisplayOrder(null); + + // Create the Choice, which fails. + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + restChoiceMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void checkCorrectIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + choice.setCorrect(null); + + // Create the Choice, which fails. + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + restChoiceMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void getAllChoices() throws Exception { + // Initialize the database + insertedChoice = choiceRepository.saveAndFlush(choice); + + // Get all the choiceList + restChoiceMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(choice.getId().intValue()))) + .andExpect(jsonPath("$.[*].optionKey").value(hasItem(DEFAULT_OPTION_KEY.toString()))) + .andExpect(jsonPath("$.[*].content").value(hasItem(DEFAULT_CONTENT))) + .andExpect(jsonPath("$.[*].displayOrder").value(hasItem(DEFAULT_DISPLAY_ORDER))) + .andExpect(jsonPath("$.[*].correct").value(hasItem(DEFAULT_CORRECT))); + } + + @Test + @Transactional + void getChoice() throws Exception { + // Initialize the database + insertedChoice = choiceRepository.saveAndFlush(choice); + + // Get the choice + restChoiceMockMvc + .perform(get(ENTITY_API_URL_ID, choice.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(choice.getId().intValue())) + .andExpect(jsonPath("$.optionKey").value(DEFAULT_OPTION_KEY.toString())) + .andExpect(jsonPath("$.content").value(DEFAULT_CONTENT)) + .andExpect(jsonPath("$.displayOrder").value(DEFAULT_DISPLAY_ORDER)) + .andExpect(jsonPath("$.correct").value(DEFAULT_CORRECT)); + } + + @Test + @Transactional + void getNonExistingChoice() throws Exception { + // Get the choice + restChoiceMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingChoice() throws Exception { + // Initialize the database + insertedChoice = choiceRepository.saveAndFlush(choice); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the choice + Choice updatedChoice = choiceRepository.findById(choice.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedChoice are not directly saved in db + em.detach(updatedChoice); + updatedChoice.optionKey(UPDATED_OPTION_KEY).content(UPDATED_CONTENT).displayOrder(UPDATED_DISPLAY_ORDER).correct(UPDATED_CORRECT); + ChoiceDTO choiceDTO = choiceMapper.toDto(updatedChoice); + + restChoiceMockMvc + .perform( + put(ENTITY_API_URL_ID, choiceDTO.getId()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO)) + ) + .andExpect(status().isOk()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedChoiceToMatchAllProperties(updatedChoice); + } + + @Test + @Transactional + void putNonExistingChoice() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + choice.setId(longCount.incrementAndGet()); + + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restChoiceMockMvc + .perform( + put(ENTITY_API_URL_ID, choiceDTO.getId()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchChoice() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + choice.setId(longCount.incrementAndGet()); + + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restChoiceMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(choiceDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamChoice() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + choice.setId(longCount.incrementAndGet()); + + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restChoiceMockMvc + .perform(put(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateChoiceWithPatch() throws Exception { + // Initialize the database + insertedChoice = choiceRepository.saveAndFlush(choice); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the choice using partial update + Choice partialUpdatedChoice = new Choice(); + partialUpdatedChoice.setId(choice.getId()); + + partialUpdatedChoice.optionKey(UPDATED_OPTION_KEY).displayOrder(UPDATED_DISPLAY_ORDER).correct(UPDATED_CORRECT); + + restChoiceMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedChoice.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedChoice)) + ) + .andExpect(status().isOk()); + + // Validate the Choice in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertChoiceUpdatableFieldsEquals(createUpdateProxyForBean(partialUpdatedChoice, choice), getPersistedChoice(choice)); + } + + @Test + @Transactional + void fullUpdateChoiceWithPatch() throws Exception { + // Initialize the database + insertedChoice = choiceRepository.saveAndFlush(choice); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the choice using partial update + Choice partialUpdatedChoice = new Choice(); + partialUpdatedChoice.setId(choice.getId()); + + partialUpdatedChoice + .optionKey(UPDATED_OPTION_KEY) + .content(UPDATED_CONTENT) + .displayOrder(UPDATED_DISPLAY_ORDER) + .correct(UPDATED_CORRECT); + + restChoiceMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedChoice.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedChoice)) + ) + .andExpect(status().isOk()); + + // Validate the Choice in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertChoiceUpdatableFieldsEquals(partialUpdatedChoice, getPersistedChoice(partialUpdatedChoice)); + } + + @Test + @Transactional + void patchNonExistingChoice() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + choice.setId(longCount.incrementAndGet()); + + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restChoiceMockMvc + .perform( + patch(ENTITY_API_URL_ID, choiceDTO.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(choiceDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchChoice() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + choice.setId(longCount.incrementAndGet()); + + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restChoiceMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(choiceDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamChoice() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + choice.setId(longCount.incrementAndGet()); + + // Create the Choice + ChoiceDTO choiceDTO = choiceMapper.toDto(choice); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restChoiceMockMvc + .perform(patch(ENTITY_API_URL).contentType("application/merge-patch+json").content(om.writeValueAsBytes(choiceDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Choice in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteChoice() throws Exception { + // Initialize the database + insertedChoice = choiceRepository.saveAndFlush(choice); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the choice + restChoiceMockMvc + .perform(delete(ENTITY_API_URL_ID, choice.getId()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return choiceRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected Choice getPersistedChoice(Choice choice) { + return choiceRepository.findById(choice.getId()).orElseThrow(); + } + + protected void assertPersistedChoiceToMatchAllProperties(Choice expectedChoice) { + assertChoiceAllPropertiesEquals(expectedChoice, getPersistedChoice(expectedChoice)); + } + + protected void assertPersistedChoiceToMatchUpdatableProperties(Choice expectedChoice) { + assertChoiceAllUpdatablePropertiesEquals(expectedChoice, getPersistedChoice(expectedChoice)); + } +} diff --git a/src/test/java/com/example/questionbank/web/rest/ExamAnswerResourceIT.java b/src/test/java/com/example/questionbank/web/rest/ExamAnswerResourceIT.java new file mode 100644 index 0000000..e09a7a7 --- /dev/null +++ b/src/test/java/com/example/questionbank/web/rest/ExamAnswerResourceIT.java @@ -0,0 +1,543 @@ +package com.example.questionbank.web.rest; + +import static com.example.questionbank.domain.ExamAnswerAsserts.*; +import static com.example.questionbank.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.example.questionbank.IntegrationTest; +import com.example.questionbank.domain.ExamAnswer; +import com.example.questionbank.domain.ExamAttempt; +import com.example.questionbank.domain.Question; +import com.example.questionbank.domain.enumeration.OptionKey; +import com.example.questionbank.repository.ExamAnswerRepository; +import com.example.questionbank.service.dto.ExamAnswerDTO; +import com.example.questionbank.service.mapper.ExamAnswerMapper; +import jakarta.persistence.EntityManager; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.ObjectMapper; + +/** + * Integration tests for the {@link ExamAnswerResource} REST controller. + */ +@IntegrationTest +@AutoConfigureMockMvc +@WithMockUser +class ExamAnswerResourceIT { + + private static final String DEFAULT_QUESTION_TEXT_SNAPSHOT = "AAAAAAAAAA"; + private static final String UPDATED_QUESTION_TEXT_SNAPSHOT = "BBBBBBBBBB"; + + private static final String DEFAULT_EXPLANATION_SNAPSHOT = "AAAAAAAAAA"; + private static final String UPDATED_EXPLANATION_SNAPSHOT = "BBBBBBBBBB"; + + private static final OptionKey DEFAULT_SELECTED_OPTION = OptionKey.A; + private static final OptionKey UPDATED_SELECTED_OPTION = OptionKey.B; + + private static final String DEFAULT_SELECTED_CONTENT_SNAPSHOT = "AAAAAAAAAA"; + private static final String UPDATED_SELECTED_CONTENT_SNAPSHOT = "BBBBBBBBBB"; + + private static final Boolean DEFAULT_CORRECT = false; + private static final Boolean UPDATED_CORRECT = true; + + private static final Integer DEFAULT_AWARDED_POINTS = 0; + private static final Integer UPDATED_AWARDED_POINTS = 1; + + private static final String ENTITY_API_URL = "/api/exam-answers"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + @Autowired + private ObjectMapper om; + + @Autowired + private ExamAnswerRepository examAnswerRepository; + + @Autowired + private ExamAnswerMapper examAnswerMapper; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restExamAnswerMockMvc; + + private ExamAnswer examAnswer; + + private ExamAnswer insertedExamAnswer; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static ExamAnswer createEntity(EntityManager em) { + ExamAnswer examAnswer = new ExamAnswer() + .questionTextSnapshot(DEFAULT_QUESTION_TEXT_SNAPSHOT) + .explanationSnapshot(DEFAULT_EXPLANATION_SNAPSHOT) + .selectedOption(DEFAULT_SELECTED_OPTION) + .selectedContentSnapshot(DEFAULT_SELECTED_CONTENT_SNAPSHOT) + .correct(DEFAULT_CORRECT) + .awardedPoints(DEFAULT_AWARDED_POINTS); + // Add required entity + Question question; + if (TestUtil.findAll(em, Question.class).isEmpty()) { + question = QuestionResourceIT.createEntity(em); + em.persist(question); + em.flush(); + } else { + question = TestUtil.findAll(em, Question.class).get(0); + } + examAnswer.setQuestion(question); + // Add required entity + ExamAttempt examAttempt; + if (TestUtil.findAll(em, ExamAttempt.class).isEmpty()) { + examAttempt = ExamAttemptResourceIT.createEntity(em); + em.persist(examAttempt); + em.flush(); + } else { + examAttempt = TestUtil.findAll(em, ExamAttempt.class).get(0); + } + examAnswer.setAttempt(examAttempt); + return examAnswer; + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static ExamAnswer createUpdatedEntity(EntityManager em) { + ExamAnswer updatedExamAnswer = new ExamAnswer() + .questionTextSnapshot(UPDATED_QUESTION_TEXT_SNAPSHOT) + .explanationSnapshot(UPDATED_EXPLANATION_SNAPSHOT) + .selectedOption(UPDATED_SELECTED_OPTION) + .selectedContentSnapshot(UPDATED_SELECTED_CONTENT_SNAPSHOT) + .correct(UPDATED_CORRECT) + .awardedPoints(UPDATED_AWARDED_POINTS); + // Add required entity + Question question; + if (TestUtil.findAll(em, Question.class).isEmpty()) { + question = QuestionResourceIT.createUpdatedEntity(em); + em.persist(question); + em.flush(); + } else { + question = TestUtil.findAll(em, Question.class).get(0); + } + updatedExamAnswer.setQuestion(question); + // Add required entity + ExamAttempt examAttempt; + if (TestUtil.findAll(em, ExamAttempt.class).isEmpty()) { + examAttempt = ExamAttemptResourceIT.createUpdatedEntity(em); + em.persist(examAttempt); + em.flush(); + } else { + examAttempt = TestUtil.findAll(em, ExamAttempt.class).get(0); + } + updatedExamAnswer.setAttempt(examAttempt); + return updatedExamAnswer; + } + + @BeforeEach + void initTest() { + examAnswer = createEntity(em); + } + + @AfterEach + void cleanup() { + if (insertedExamAnswer != null) { + examAnswerRepository.delete(insertedExamAnswer); + insertedExamAnswer = null; + } + } + + @Test + @Transactional + void createExamAnswer() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + var returnedExamAnswerDTO = om.readValue( + restExamAnswerMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAnswerDTO))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + ExamAnswerDTO.class + ); + + // Validate the ExamAnswer in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + var returnedExamAnswer = examAnswerMapper.toEntity(returnedExamAnswerDTO); + assertExamAnswerUpdatableFieldsEquals(returnedExamAnswer, getPersistedExamAnswer(returnedExamAnswer)); + + insertedExamAnswer = returnedExamAnswer; + } + + @Test + @Transactional + void createExamAnswerWithExistingId() throws Exception { + // Create the ExamAnswer with an existing ID + examAnswer.setId(1L); + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restExamAnswerMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAnswerDTO))) + .andExpect(status().isBadRequest()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void checkQuestionTextSnapshotIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + examAnswer.setQuestionTextSnapshot(null); + + // Create the ExamAnswer, which fails. + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + restExamAnswerMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAnswerDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void getAllExamAnswers() throws Exception { + // Initialize the database + insertedExamAnswer = examAnswerRepository.saveAndFlush(examAnswer); + + // Get all the examAnswerList + restExamAnswerMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(examAnswer.getId().intValue()))) + .andExpect(jsonPath("$.[*].questionTextSnapshot").value(hasItem(DEFAULT_QUESTION_TEXT_SNAPSHOT))) + .andExpect(jsonPath("$.[*].explanationSnapshot").value(hasItem(DEFAULT_EXPLANATION_SNAPSHOT))) + .andExpect(jsonPath("$.[*].selectedOption").value(hasItem(DEFAULT_SELECTED_OPTION.toString()))) + .andExpect(jsonPath("$.[*].selectedContentSnapshot").value(hasItem(DEFAULT_SELECTED_CONTENT_SNAPSHOT))) + .andExpect(jsonPath("$.[*].correct").value(hasItem(DEFAULT_CORRECT))) + .andExpect(jsonPath("$.[*].awardedPoints").value(hasItem(DEFAULT_AWARDED_POINTS))); + } + + @Test + @Transactional + void getExamAnswer() throws Exception { + // Initialize the database + insertedExamAnswer = examAnswerRepository.saveAndFlush(examAnswer); + + // Get the examAnswer + restExamAnswerMockMvc + .perform(get(ENTITY_API_URL_ID, examAnswer.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(examAnswer.getId().intValue())) + .andExpect(jsonPath("$.questionTextSnapshot").value(DEFAULT_QUESTION_TEXT_SNAPSHOT)) + .andExpect(jsonPath("$.explanationSnapshot").value(DEFAULT_EXPLANATION_SNAPSHOT)) + .andExpect(jsonPath("$.selectedOption").value(DEFAULT_SELECTED_OPTION.toString())) + .andExpect(jsonPath("$.selectedContentSnapshot").value(DEFAULT_SELECTED_CONTENT_SNAPSHOT)) + .andExpect(jsonPath("$.correct").value(DEFAULT_CORRECT)) + .andExpect(jsonPath("$.awardedPoints").value(DEFAULT_AWARDED_POINTS)); + } + + @Test + @Transactional + void getNonExistingExamAnswer() throws Exception { + // Get the examAnswer + restExamAnswerMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingExamAnswer() throws Exception { + // Initialize the database + insertedExamAnswer = examAnswerRepository.saveAndFlush(examAnswer); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the examAnswer + ExamAnswer updatedExamAnswer = examAnswerRepository.findById(examAnswer.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedExamAnswer are not directly saved in db + em.detach(updatedExamAnswer); + updatedExamAnswer + .questionTextSnapshot(UPDATED_QUESTION_TEXT_SNAPSHOT) + .explanationSnapshot(UPDATED_EXPLANATION_SNAPSHOT) + .selectedOption(UPDATED_SELECTED_OPTION) + .selectedContentSnapshot(UPDATED_SELECTED_CONTENT_SNAPSHOT) + .correct(UPDATED_CORRECT) + .awardedPoints(UPDATED_AWARDED_POINTS); + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(updatedExamAnswer); + + restExamAnswerMockMvc + .perform( + put(ENTITY_API_URL_ID, examAnswerDTO.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(examAnswerDTO)) + ) + .andExpect(status().isOk()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedExamAnswerToMatchAllProperties(updatedExamAnswer); + } + + @Test + @Transactional + void putNonExistingExamAnswer() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAnswer.setId(longCount.incrementAndGet()); + + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restExamAnswerMockMvc + .perform( + put(ENTITY_API_URL_ID, examAnswerDTO.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(examAnswerDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchExamAnswer() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAnswer.setId(longCount.incrementAndGet()); + + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAnswerMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(examAnswerDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamExamAnswer() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAnswer.setId(longCount.incrementAndGet()); + + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAnswerMockMvc + .perform(put(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAnswerDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateExamAnswerWithPatch() throws Exception { + // Initialize the database + insertedExamAnswer = examAnswerRepository.saveAndFlush(examAnswer); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the examAnswer using partial update + ExamAnswer partialUpdatedExamAnswer = new ExamAnswer(); + partialUpdatedExamAnswer.setId(examAnswer.getId()); + + partialUpdatedExamAnswer.correct(UPDATED_CORRECT); + + restExamAnswerMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedExamAnswer.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedExamAnswer)) + ) + .andExpect(status().isOk()); + + // Validate the ExamAnswer in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertExamAnswerUpdatableFieldsEquals( + createUpdateProxyForBean(partialUpdatedExamAnswer, examAnswer), + getPersistedExamAnswer(examAnswer) + ); + } + + @Test + @Transactional + void fullUpdateExamAnswerWithPatch() throws Exception { + // Initialize the database + insertedExamAnswer = examAnswerRepository.saveAndFlush(examAnswer); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the examAnswer using partial update + ExamAnswer partialUpdatedExamAnswer = new ExamAnswer(); + partialUpdatedExamAnswer.setId(examAnswer.getId()); + + partialUpdatedExamAnswer + .questionTextSnapshot(UPDATED_QUESTION_TEXT_SNAPSHOT) + .explanationSnapshot(UPDATED_EXPLANATION_SNAPSHOT) + .selectedOption(UPDATED_SELECTED_OPTION) + .selectedContentSnapshot(UPDATED_SELECTED_CONTENT_SNAPSHOT) + .correct(UPDATED_CORRECT) + .awardedPoints(UPDATED_AWARDED_POINTS); + + restExamAnswerMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedExamAnswer.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedExamAnswer)) + ) + .andExpect(status().isOk()); + + // Validate the ExamAnswer in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertExamAnswerUpdatableFieldsEquals(partialUpdatedExamAnswer, getPersistedExamAnswer(partialUpdatedExamAnswer)); + } + + @Test + @Transactional + void patchNonExistingExamAnswer() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAnswer.setId(longCount.incrementAndGet()); + + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restExamAnswerMockMvc + .perform( + patch(ENTITY_API_URL_ID, examAnswerDTO.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(examAnswerDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchExamAnswer() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAnswer.setId(longCount.incrementAndGet()); + + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAnswerMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(examAnswerDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamExamAnswer() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAnswer.setId(longCount.incrementAndGet()); + + // Create the ExamAnswer + ExamAnswerDTO examAnswerDTO = examAnswerMapper.toDto(examAnswer); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAnswerMockMvc + .perform(patch(ENTITY_API_URL).contentType("application/merge-patch+json").content(om.writeValueAsBytes(examAnswerDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the ExamAnswer in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteExamAnswer() throws Exception { + // Initialize the database + insertedExamAnswer = examAnswerRepository.saveAndFlush(examAnswer); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the examAnswer + restExamAnswerMockMvc + .perform(delete(ENTITY_API_URL_ID, examAnswer.getId()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return examAnswerRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected ExamAnswer getPersistedExamAnswer(ExamAnswer examAnswer) { + return examAnswerRepository.findById(examAnswer.getId()).orElseThrow(); + } + + protected void assertPersistedExamAnswerToMatchAllProperties(ExamAnswer expectedExamAnswer) { + assertExamAnswerAllPropertiesEquals(expectedExamAnswer, getPersistedExamAnswer(expectedExamAnswer)); + } + + protected void assertPersistedExamAnswerToMatchUpdatableProperties(ExamAnswer expectedExamAnswer) { + assertExamAnswerAllUpdatablePropertiesEquals(expectedExamAnswer, getPersistedExamAnswer(expectedExamAnswer)); + } +} diff --git a/src/test/java/com/example/questionbank/web/rest/ExamAttemptResourceIT.java b/src/test/java/com/example/questionbank/web/rest/ExamAttemptResourceIT.java new file mode 100644 index 0000000..7b692d5 --- /dev/null +++ b/src/test/java/com/example/questionbank/web/rest/ExamAttemptResourceIT.java @@ -0,0 +1,565 @@ +package com.example.questionbank.web.rest; + +import static com.example.questionbank.domain.ExamAttemptAsserts.*; +import static com.example.questionbank.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.example.questionbank.IntegrationTest; +import com.example.questionbank.domain.ExamAttempt; +import com.example.questionbank.domain.Subject; +import com.example.questionbank.domain.User; +import com.example.questionbank.domain.enumeration.AttemptStatus; +import com.example.questionbank.repository.ExamAttemptRepository; +import com.example.questionbank.repository.UserRepository; +import com.example.questionbank.service.ExamAttemptService; +import com.example.questionbank.service.dto.ExamAttemptDTO; +import com.example.questionbank.service.mapper.ExamAttemptMapper; +import jakarta.persistence.EntityManager; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.ObjectMapper; + +/** + * Integration tests for the {@link ExamAttemptResource} REST controller. + */ +@IntegrationTest +@ExtendWith(MockitoExtension.class) +@AutoConfigureMockMvc +@WithMockUser +class ExamAttemptResourceIT { + + private static final Instant DEFAULT_STARTED_AT = Instant.ofEpochMilli(0L); + private static final Instant UPDATED_STARTED_AT = Instant.ofEpochMilli(1792485949603L); + + private static final Instant DEFAULT_SUBMITTED_AT = Instant.ofEpochMilli(0L); + private static final Instant UPDATED_SUBMITTED_AT = Instant.ofEpochMilli(1792485949603L); + + private static final AttemptStatus DEFAULT_STATUS = AttemptStatus.IN_PROGRESS; + private static final AttemptStatus UPDATED_STATUS = AttemptStatus.SUBMITTED; + + private static final Integer DEFAULT_SCORE = 0; + private static final Integer UPDATED_SCORE = 1; + + private static final String ENTITY_API_URL = "/api/exam-attempts"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + @Autowired + private ObjectMapper om; + + @Autowired + private ExamAttemptRepository examAttemptRepository; + + @Autowired + private UserRepository userRepository; + + @Mock + private ExamAttemptRepository examAttemptRepositoryMock; + + @Autowired + private ExamAttemptMapper examAttemptMapper; + + @Mock + private ExamAttemptService examAttemptServiceMock; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restExamAttemptMockMvc; + + private ExamAttempt examAttempt; + + private ExamAttempt insertedExamAttempt; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static ExamAttempt createEntity(EntityManager em) { + ExamAttempt examAttempt = new ExamAttempt() + .startedAt(DEFAULT_STARTED_AT) + .submittedAt(DEFAULT_SUBMITTED_AT) + .status(DEFAULT_STATUS) + .score(DEFAULT_SCORE); + // Add required entity + Subject subject; + if (TestUtil.findAll(em, Subject.class).isEmpty()) { + subject = SubjectResourceIT.createEntity(); + em.persist(subject); + em.flush(); + } else { + subject = TestUtil.findAll(em, Subject.class).get(0); + } + examAttempt.setSubject(subject); + // Add required entity + User user = UserResourceIT.createEntity(); + em.persist(user); + em.flush(); + examAttempt.setUser(user); + return examAttempt; + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static ExamAttempt createUpdatedEntity(EntityManager em) { + ExamAttempt updatedExamAttempt = new ExamAttempt() + .startedAt(UPDATED_STARTED_AT) + .submittedAt(UPDATED_SUBMITTED_AT) + .status(UPDATED_STATUS) + .score(UPDATED_SCORE); + // Add required entity + Subject subject; + if (TestUtil.findAll(em, Subject.class).isEmpty()) { + subject = SubjectResourceIT.createUpdatedEntity(); + em.persist(subject); + em.flush(); + } else { + subject = TestUtil.findAll(em, Subject.class).get(0); + } + updatedExamAttempt.setSubject(subject); + // Add required entity + User user = UserResourceIT.createEntity(); + em.persist(user); + em.flush(); + updatedExamAttempt.setUser(user); + return updatedExamAttempt; + } + + @BeforeEach + void initTest() { + examAttempt = createEntity(em); + } + + @AfterEach + void cleanup() { + if (insertedExamAttempt != null) { + examAttemptRepository.delete(insertedExamAttempt); + insertedExamAttempt = null; + } + } + + @Test + @Transactional + void createExamAttempt() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + var returnedExamAttemptDTO = om.readValue( + restExamAttemptMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAttemptDTO))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + ExamAttemptDTO.class + ); + + // Validate the ExamAttempt in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + var returnedExamAttempt = examAttemptMapper.toEntity(returnedExamAttemptDTO); + assertExamAttemptUpdatableFieldsEquals(returnedExamAttempt, getPersistedExamAttempt(returnedExamAttempt)); + + insertedExamAttempt = returnedExamAttempt; + } + + @Test + @Transactional + void createExamAttemptWithExistingId() throws Exception { + // Create the ExamAttempt with an existing ID + examAttempt.setId(1L); + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restExamAttemptMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAttemptDTO))) + .andExpect(status().isBadRequest()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void checkStartedAtIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + examAttempt.setStartedAt(null); + + // Create the ExamAttempt, which fails. + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + restExamAttemptMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAttemptDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void checkStatusIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + examAttempt.setStatus(null); + + // Create the ExamAttempt, which fails. + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + restExamAttemptMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAttemptDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void getAllExamAttempts() throws Exception { + // Initialize the database + insertedExamAttempt = examAttemptRepository.saveAndFlush(examAttempt); + + // Get all the examAttemptList + restExamAttemptMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(examAttempt.getId().intValue()))) + .andExpect(jsonPath("$.[*].startedAt").value(hasItem(DEFAULT_STARTED_AT.toString()))) + .andExpect(jsonPath("$.[*].submittedAt").value(hasItem(DEFAULT_SUBMITTED_AT.toString()))) + .andExpect(jsonPath("$.[*].status").value(hasItem(DEFAULT_STATUS.toString()))) + .andExpect(jsonPath("$.[*].score").value(hasItem(DEFAULT_SCORE))); + } + + @SuppressWarnings({ "unchecked" }) + void getAllExamAttemptsWithEagerRelationshipsIsEnabled() throws Exception { + when(examAttemptServiceMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restExamAttemptMockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")).andExpect(status().isOk()); + + verify(examAttemptServiceMock, times(1)).findAllWithEagerRelationships(any()); + } + + @SuppressWarnings({ "unchecked" }) + void getAllExamAttemptsWithEagerRelationshipsIsNotEnabled() throws Exception { + when(examAttemptServiceMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restExamAttemptMockMvc.perform(get(ENTITY_API_URL + "?eagerload=false")).andExpect(status().isOk()); + verify(examAttemptRepositoryMock, times(1)).findAll(any(Pageable.class)); + } + + @Test + @Transactional + void getExamAttempt() throws Exception { + // Initialize the database + insertedExamAttempt = examAttemptRepository.saveAndFlush(examAttempt); + + // Get the examAttempt + restExamAttemptMockMvc + .perform(get(ENTITY_API_URL_ID, examAttempt.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(examAttempt.getId().intValue())) + .andExpect(jsonPath("$.startedAt").value(DEFAULT_STARTED_AT.toString())) + .andExpect(jsonPath("$.submittedAt").value(DEFAULT_SUBMITTED_AT.toString())) + .andExpect(jsonPath("$.status").value(DEFAULT_STATUS.toString())) + .andExpect(jsonPath("$.score").value(DEFAULT_SCORE)); + } + + @Test + @Transactional + void getNonExistingExamAttempt() throws Exception { + // Get the examAttempt + restExamAttemptMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingExamAttempt() throws Exception { + // Initialize the database + insertedExamAttempt = examAttemptRepository.saveAndFlush(examAttempt); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the examAttempt + ExamAttempt updatedExamAttempt = examAttemptRepository.findById(examAttempt.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedExamAttempt are not directly saved in db + em.detach(updatedExamAttempt); + updatedExamAttempt.startedAt(UPDATED_STARTED_AT).submittedAt(UPDATED_SUBMITTED_AT).status(UPDATED_STATUS).score(UPDATED_SCORE); + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(updatedExamAttempt); + + restExamAttemptMockMvc + .perform( + put(ENTITY_API_URL_ID, examAttemptDTO.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(examAttemptDTO)) + ) + .andExpect(status().isOk()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedExamAttemptToMatchAllProperties(updatedExamAttempt); + } + + @Test + @Transactional + void putNonExistingExamAttempt() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAttempt.setId(longCount.incrementAndGet()); + + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restExamAttemptMockMvc + .perform( + put(ENTITY_API_URL_ID, examAttemptDTO.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(examAttemptDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchExamAttempt() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAttempt.setId(longCount.incrementAndGet()); + + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAttemptMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(examAttemptDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamExamAttempt() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAttempt.setId(longCount.incrementAndGet()); + + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAttemptMockMvc + .perform(put(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(examAttemptDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateExamAttemptWithPatch() throws Exception { + // Initialize the database + insertedExamAttempt = examAttemptRepository.saveAndFlush(examAttempt); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the examAttempt using partial update + ExamAttempt partialUpdatedExamAttempt = new ExamAttempt(); + partialUpdatedExamAttempt.setId(examAttempt.getId()); + + partialUpdatedExamAttempt.startedAt(UPDATED_STARTED_AT).status(UPDATED_STATUS).score(UPDATED_SCORE); + + restExamAttemptMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedExamAttempt.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedExamAttempt)) + ) + .andExpect(status().isOk()); + + // Validate the ExamAttempt in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertExamAttemptUpdatableFieldsEquals( + createUpdateProxyForBean(partialUpdatedExamAttempt, examAttempt), + getPersistedExamAttempt(examAttempt) + ); + } + + @Test + @Transactional + void fullUpdateExamAttemptWithPatch() throws Exception { + // Initialize the database + insertedExamAttempt = examAttemptRepository.saveAndFlush(examAttempt); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the examAttempt using partial update + ExamAttempt partialUpdatedExamAttempt = new ExamAttempt(); + partialUpdatedExamAttempt.setId(examAttempt.getId()); + + partialUpdatedExamAttempt + .startedAt(UPDATED_STARTED_AT) + .submittedAt(UPDATED_SUBMITTED_AT) + .status(UPDATED_STATUS) + .score(UPDATED_SCORE); + + restExamAttemptMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedExamAttempt.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedExamAttempt)) + ) + .andExpect(status().isOk()); + + // Validate the ExamAttempt in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertExamAttemptUpdatableFieldsEquals(partialUpdatedExamAttempt, getPersistedExamAttempt(partialUpdatedExamAttempt)); + } + + @Test + @Transactional + void patchNonExistingExamAttempt() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAttempt.setId(longCount.incrementAndGet()); + + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restExamAttemptMockMvc + .perform( + patch(ENTITY_API_URL_ID, examAttemptDTO.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(examAttemptDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchExamAttempt() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAttempt.setId(longCount.incrementAndGet()); + + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAttemptMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(examAttemptDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamExamAttempt() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + examAttempt.setId(longCount.incrementAndGet()); + + // Create the ExamAttempt + ExamAttemptDTO examAttemptDTO = examAttemptMapper.toDto(examAttempt); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restExamAttemptMockMvc + .perform(patch(ENTITY_API_URL).contentType("application/merge-patch+json").content(om.writeValueAsBytes(examAttemptDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the ExamAttempt in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteExamAttempt() throws Exception { + // Initialize the database + insertedExamAttempt = examAttemptRepository.saveAndFlush(examAttempt); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the examAttempt + restExamAttemptMockMvc + .perform(delete(ENTITY_API_URL_ID, examAttempt.getId()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return examAttemptRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected ExamAttempt getPersistedExamAttempt(ExamAttempt examAttempt) { + return examAttemptRepository.findById(examAttempt.getId()).orElseThrow(); + } + + protected void assertPersistedExamAttemptToMatchAllProperties(ExamAttempt expectedExamAttempt) { + assertExamAttemptAllPropertiesEquals(expectedExamAttempt, getPersistedExamAttempt(expectedExamAttempt)); + } + + protected void assertPersistedExamAttemptToMatchUpdatableProperties(ExamAttempt expectedExamAttempt) { + assertExamAttemptAllUpdatablePropertiesEquals(expectedExamAttempt, getPersistedExamAttempt(expectedExamAttempt)); + } +} diff --git a/src/test/java/com/example/questionbank/web/rest/QuestionResourceIT.java b/src/test/java/com/example/questionbank/web/rest/QuestionResourceIT.java new file mode 100644 index 0000000..01d38c0 --- /dev/null +++ b/src/test/java/com/example/questionbank/web/rest/QuestionResourceIT.java @@ -0,0 +1,526 @@ +package com.example.questionbank.web.rest; + +import static com.example.questionbank.domain.QuestionAsserts.*; +import static com.example.questionbank.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.example.questionbank.IntegrationTest; +import com.example.questionbank.domain.Question; +import com.example.questionbank.domain.Subject; +import com.example.questionbank.repository.QuestionRepository; +import com.example.questionbank.service.QuestionService; +import com.example.questionbank.service.dto.QuestionDTO; +import com.example.questionbank.service.mapper.QuestionMapper; +import jakarta.persistence.EntityManager; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.ObjectMapper; + +/** + * Integration tests for the {@link QuestionResource} REST controller. + */ +@IntegrationTest +@ExtendWith(MockitoExtension.class) +@AutoConfigureMockMvc +@WithMockUser +class QuestionResourceIT { + + private static final String DEFAULT_PROMPT = "AAAAAAAAAA"; + private static final String UPDATED_PROMPT = "BBBBBBBBBB"; + + private static final String DEFAULT_EXPLANATION = "AAAAAAAAAA"; + private static final String UPDATED_EXPLANATION = "BBBBBBBBBB"; + + private static final Boolean DEFAULT_ACTIVE = false; + private static final Boolean UPDATED_ACTIVE = true; + + private static final String ENTITY_API_URL = "/api/questions"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + @Autowired + private ObjectMapper om; + + @Autowired + private QuestionRepository questionRepository; + + @Mock + private QuestionRepository questionRepositoryMock; + + @Autowired + private QuestionMapper questionMapper; + + @Mock + private QuestionService questionServiceMock; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restQuestionMockMvc; + + private Question question; + + private Question insertedQuestion; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Question createEntity(EntityManager em) { + Question question = new Question().prompt(DEFAULT_PROMPT).explanation(DEFAULT_EXPLANATION).active(DEFAULT_ACTIVE); + // Add required entity + Subject subject; + if (TestUtil.findAll(em, Subject.class).isEmpty()) { + subject = SubjectResourceIT.createEntity(); + em.persist(subject); + em.flush(); + } else { + subject = TestUtil.findAll(em, Subject.class).get(0); + } + question.setSubject(subject); + return question; + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Question createUpdatedEntity(EntityManager em) { + Question updatedQuestion = new Question().prompt(UPDATED_PROMPT).explanation(UPDATED_EXPLANATION).active(UPDATED_ACTIVE); + // Add required entity + Subject subject; + if (TestUtil.findAll(em, Subject.class).isEmpty()) { + subject = SubjectResourceIT.createUpdatedEntity(); + em.persist(subject); + em.flush(); + } else { + subject = TestUtil.findAll(em, Subject.class).get(0); + } + updatedQuestion.setSubject(subject); + return updatedQuestion; + } + + @BeforeEach + void initTest() { + question = createEntity(em); + } + + @AfterEach + void cleanup() { + if (insertedQuestion != null) { + questionRepository.delete(insertedQuestion); + insertedQuestion = null; + } + } + + @Test + @Transactional + void createQuestion() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + var returnedQuestionDTO = om.readValue( + restQuestionMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(questionDTO))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + QuestionDTO.class + ); + + // Validate the Question in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + var returnedQuestion = questionMapper.toEntity(returnedQuestionDTO); + assertQuestionUpdatableFieldsEquals(returnedQuestion, getPersistedQuestion(returnedQuestion)); + + insertedQuestion = returnedQuestion; + } + + @Test + @Transactional + void createQuestionWithExistingId() throws Exception { + // Create the Question with an existing ID + question.setId(1L); + QuestionDTO questionDTO = questionMapper.toDto(question); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restQuestionMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(questionDTO))) + .andExpect(status().isBadRequest()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void checkPromptIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + question.setPrompt(null); + + // Create the Question, which fails. + QuestionDTO questionDTO = questionMapper.toDto(question); + + restQuestionMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(questionDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void checkActiveIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + question.setActive(null); + + // Create the Question, which fails. + QuestionDTO questionDTO = questionMapper.toDto(question); + + restQuestionMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(questionDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void getAllQuestions() throws Exception { + // Initialize the database + insertedQuestion = questionRepository.saveAndFlush(question); + + // Get all the questionList + restQuestionMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(question.getId().intValue()))) + .andExpect(jsonPath("$.[*].prompt").value(hasItem(DEFAULT_PROMPT))) + .andExpect(jsonPath("$.[*].explanation").value(hasItem(DEFAULT_EXPLANATION))) + .andExpect(jsonPath("$.[*].active").value(hasItem(DEFAULT_ACTIVE))); + } + + @SuppressWarnings({ "unchecked" }) + void getAllQuestionsWithEagerRelationshipsIsEnabled() throws Exception { + when(questionServiceMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restQuestionMockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")).andExpect(status().isOk()); + + verify(questionServiceMock, times(1)).findAllWithEagerRelationships(any()); + } + + @SuppressWarnings({ "unchecked" }) + void getAllQuestionsWithEagerRelationshipsIsNotEnabled() throws Exception { + when(questionServiceMock.findAllWithEagerRelationships(any())).thenReturn(new PageImpl(new ArrayList<>())); + + restQuestionMockMvc.perform(get(ENTITY_API_URL + "?eagerload=false")).andExpect(status().isOk()); + verify(questionRepositoryMock, times(1)).findAll(any(Pageable.class)); + } + + @Test + @Transactional + void getQuestion() throws Exception { + // Initialize the database + insertedQuestion = questionRepository.saveAndFlush(question); + + // Get the question + restQuestionMockMvc + .perform(get(ENTITY_API_URL_ID, question.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(question.getId().intValue())) + .andExpect(jsonPath("$.prompt").value(DEFAULT_PROMPT)) + .andExpect(jsonPath("$.explanation").value(DEFAULT_EXPLANATION)) + .andExpect(jsonPath("$.active").value(DEFAULT_ACTIVE)); + } + + @Test + @Transactional + void getNonExistingQuestion() throws Exception { + // Get the question + restQuestionMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingQuestion() throws Exception { + // Initialize the database + insertedQuestion = questionRepository.saveAndFlush(question); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the question + Question updatedQuestion = questionRepository.findById(question.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedQuestion are not directly saved in db + em.detach(updatedQuestion); + updatedQuestion.prompt(UPDATED_PROMPT).explanation(UPDATED_EXPLANATION).active(UPDATED_ACTIVE); + QuestionDTO questionDTO = questionMapper.toDto(updatedQuestion); + + restQuestionMockMvc + .perform( + put(ENTITY_API_URL_ID, questionDTO.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(questionDTO)) + ) + .andExpect(status().isOk()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedQuestionToMatchAllProperties(updatedQuestion); + } + + @Test + @Transactional + void putNonExistingQuestion() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + question.setId(longCount.incrementAndGet()); + + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restQuestionMockMvc + .perform( + put(ENTITY_API_URL_ID, questionDTO.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(questionDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchQuestion() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + question.setId(longCount.incrementAndGet()); + + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restQuestionMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(questionDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamQuestion() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + question.setId(longCount.incrementAndGet()); + + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restQuestionMockMvc + .perform(put(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(questionDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateQuestionWithPatch() throws Exception { + // Initialize the database + insertedQuestion = questionRepository.saveAndFlush(question); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the question using partial update + Question partialUpdatedQuestion = new Question(); + partialUpdatedQuestion.setId(question.getId()); + + restQuestionMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedQuestion.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedQuestion)) + ) + .andExpect(status().isOk()); + + // Validate the Question in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertQuestionUpdatableFieldsEquals(createUpdateProxyForBean(partialUpdatedQuestion, question), getPersistedQuestion(question)); + } + + @Test + @Transactional + void fullUpdateQuestionWithPatch() throws Exception { + // Initialize the database + insertedQuestion = questionRepository.saveAndFlush(question); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the question using partial update + Question partialUpdatedQuestion = new Question(); + partialUpdatedQuestion.setId(question.getId()); + + partialUpdatedQuestion.prompt(UPDATED_PROMPT).explanation(UPDATED_EXPLANATION).active(UPDATED_ACTIVE); + + restQuestionMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedQuestion.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedQuestion)) + ) + .andExpect(status().isOk()); + + // Validate the Question in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertQuestionUpdatableFieldsEquals(partialUpdatedQuestion, getPersistedQuestion(partialUpdatedQuestion)); + } + + @Test + @Transactional + void patchNonExistingQuestion() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + question.setId(longCount.incrementAndGet()); + + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restQuestionMockMvc + .perform( + patch(ENTITY_API_URL_ID, questionDTO.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(questionDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchQuestion() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + question.setId(longCount.incrementAndGet()); + + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restQuestionMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(questionDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamQuestion() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + question.setId(longCount.incrementAndGet()); + + // Create the Question + QuestionDTO questionDTO = questionMapper.toDto(question); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restQuestionMockMvc + .perform(patch(ENTITY_API_URL).contentType("application/merge-patch+json").content(om.writeValueAsBytes(questionDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Question in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteQuestion() throws Exception { + // Initialize the database + insertedQuestion = questionRepository.saveAndFlush(question); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the question + restQuestionMockMvc + .perform(delete(ENTITY_API_URL_ID, question.getId()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return questionRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected Question getPersistedQuestion(Question question) { + return questionRepository.findById(question.getId()).orElseThrow(); + } + + protected void assertPersistedQuestionToMatchAllProperties(Question expectedQuestion) { + assertQuestionAllPropertiesEquals(expectedQuestion, getPersistedQuestion(expectedQuestion)); + } + + protected void assertPersistedQuestionToMatchUpdatableProperties(Question expectedQuestion) { + assertQuestionAllUpdatablePropertiesEquals(expectedQuestion, getPersistedQuestion(expectedQuestion)); + } +} diff --git a/src/test/java/com/example/questionbank/web/rest/SubjectResourceIT.java b/src/test/java/com/example/questionbank/web/rest/SubjectResourceIT.java new file mode 100644 index 0000000..6881ec1 --- /dev/null +++ b/src/test/java/com/example/questionbank/web/rest/SubjectResourceIT.java @@ -0,0 +1,469 @@ +package com.example.questionbank.web.rest; + +import static com.example.questionbank.domain.SubjectAsserts.*; +import static com.example.questionbank.web.rest.TestUtil.createUpdateProxyForBean; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import com.example.questionbank.IntegrationTest; +import com.example.questionbank.domain.Subject; +import com.example.questionbank.repository.SubjectRepository; +import com.example.questionbank.service.dto.SubjectDTO; +import com.example.questionbank.service.mapper.SubjectMapper; +import jakarta.persistence.EntityManager; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.ObjectMapper; + +/** + * Integration tests for the {@link SubjectResource} REST controller. + */ +@IntegrationTest +@AutoConfigureMockMvc +@WithMockUser +class SubjectResourceIT { + + private static final String DEFAULT_NAME = "AAAAAAAAAA"; + private static final String UPDATED_NAME = "BBBBBBBBBB"; + + private static final String DEFAULT_DESCRIPTION = "AAAAAAAAAA"; + private static final String UPDATED_DESCRIPTION = "BBBBBBBBBB"; + + private static final Boolean DEFAULT_ACTIVE = false; + private static final Boolean UPDATED_ACTIVE = true; + + private static final String ENTITY_API_URL = "/api/subjects"; + private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{id}"; + + private static final Random random = new Random(); + private static final AtomicLong longCount = new AtomicLong(random.nextInt() + 2L * Integer.MAX_VALUE); + + @Autowired + private ObjectMapper om; + + @Autowired + private SubjectRepository subjectRepository; + + @Autowired + private SubjectMapper subjectMapper; + + @Autowired + private EntityManager em; + + @Autowired + private MockMvc restSubjectMockMvc; + + private Subject subject; + + private Subject insertedSubject; + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Subject createEntity() { + return new Subject().name(DEFAULT_NAME).description(DEFAULT_DESCRIPTION).active(DEFAULT_ACTIVE); + } + + /** + * Create an updated entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Subject createUpdatedEntity() { + return new Subject().name(UPDATED_NAME).description(UPDATED_DESCRIPTION).active(UPDATED_ACTIVE); + } + + @BeforeEach + void initTest() { + subject = createEntity(); + } + + @AfterEach + void cleanup() { + if (insertedSubject != null) { + subjectRepository.delete(insertedSubject); + insertedSubject = null; + } + } + + @Test + @Transactional + void createSubject() throws Exception { + long databaseSizeBeforeCreate = getRepositoryCount(); + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + var returnedSubjectDTO = om.readValue( + restSubjectMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getContentAsString(), + SubjectDTO.class + ); + + // Validate the Subject in the database + assertIncrementedRepositoryCount(databaseSizeBeforeCreate); + var returnedSubject = subjectMapper.toEntity(returnedSubjectDTO); + assertSubjectUpdatableFieldsEquals(returnedSubject, getPersistedSubject(returnedSubject)); + + insertedSubject = returnedSubject; + } + + @Test + @Transactional + void createSubjectWithExistingId() throws Exception { + // Create the Subject with an existing ID + subject.setId(1L); + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + long databaseSizeBeforeCreate = getRepositoryCount(); + + // An entity with an existing ID cannot be created, so this API call must fail + restSubjectMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO))) + .andExpect(status().isBadRequest()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeCreate); + } + + @Test + @Transactional + void checkNameIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + subject.setName(null); + + // Create the Subject, which fails. + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + restSubjectMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void checkActiveIsRequired() throws Exception { + long databaseSizeBeforeTest = getRepositoryCount(); + // set the field null + subject.setActive(null); + + // Create the Subject, which fails. + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + restSubjectMockMvc + .perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO))) + .andExpect(status().isBadRequest()); + + assertSameRepositoryCount(databaseSizeBeforeTest); + } + + @Test + @Transactional + void getAllSubjects() throws Exception { + // Initialize the database + insertedSubject = subjectRepository.saveAndFlush(subject); + + // Get all the subjectList + restSubjectMockMvc + .perform(get(ENTITY_API_URL + "?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(subject.getId().intValue()))) + .andExpect(jsonPath("$.[*].name").value(hasItem(DEFAULT_NAME))) + .andExpect(jsonPath("$.[*].description").value(hasItem(DEFAULT_DESCRIPTION))) + .andExpect(jsonPath("$.[*].active").value(hasItem(DEFAULT_ACTIVE))); + } + + @Test + @Transactional + void getSubject() throws Exception { + // Initialize the database + insertedSubject = subjectRepository.saveAndFlush(subject); + + // Get the subject + restSubjectMockMvc + .perform(get(ENTITY_API_URL_ID, subject.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.id").value(subject.getId().intValue())) + .andExpect(jsonPath("$.name").value(DEFAULT_NAME)) + .andExpect(jsonPath("$.description").value(DEFAULT_DESCRIPTION)) + .andExpect(jsonPath("$.active").value(DEFAULT_ACTIVE)); + } + + @Test + @Transactional + void getNonExistingSubject() throws Exception { + // Get the subject + restSubjectMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound()); + } + + @Test + @Transactional + void putExistingSubject() throws Exception { + // Initialize the database + insertedSubject = subjectRepository.saveAndFlush(subject); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the subject + Subject updatedSubject = subjectRepository.findById(subject.getId()).orElseThrow(); + // Disconnect from session so that the updates on updatedSubject are not directly saved in db + em.detach(updatedSubject); + updatedSubject.name(UPDATED_NAME).description(UPDATED_DESCRIPTION).active(UPDATED_ACTIVE); + SubjectDTO subjectDTO = subjectMapper.toDto(updatedSubject); + + restSubjectMockMvc + .perform( + put(ENTITY_API_URL_ID, subjectDTO.getId()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO)) + ) + .andExpect(status().isOk()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertPersistedSubjectToMatchAllProperties(updatedSubject); + } + + @Test + @Transactional + void putNonExistingSubject() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + subject.setId(longCount.incrementAndGet()); + + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restSubjectMockMvc + .perform( + put(ENTITY_API_URL_ID, subjectDTO.getId()).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithIdMismatchSubject() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + subject.setId(longCount.incrementAndGet()); + + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restSubjectMockMvc + .perform( + put(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType(MediaType.APPLICATION_JSON) + .content(om.writeValueAsBytes(subjectDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void putWithMissingIdPathParamSubject() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + subject.setId(longCount.incrementAndGet()); + + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restSubjectMockMvc + .perform(put(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(subjectDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void partialUpdateSubjectWithPatch() throws Exception { + // Initialize the database + insertedSubject = subjectRepository.saveAndFlush(subject); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the subject using partial update + Subject partialUpdatedSubject = new Subject(); + partialUpdatedSubject.setId(subject.getId()); + + partialUpdatedSubject.active(UPDATED_ACTIVE); + + restSubjectMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedSubject.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedSubject)) + ) + .andExpect(status().isOk()); + + // Validate the Subject in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertSubjectUpdatableFieldsEquals(createUpdateProxyForBean(partialUpdatedSubject, subject), getPersistedSubject(subject)); + } + + @Test + @Transactional + void fullUpdateSubjectWithPatch() throws Exception { + // Initialize the database + insertedSubject = subjectRepository.saveAndFlush(subject); + + long databaseSizeBeforeUpdate = getRepositoryCount(); + + // Update the subject using partial update + Subject partialUpdatedSubject = new Subject(); + partialUpdatedSubject.setId(subject.getId()); + + partialUpdatedSubject.name(UPDATED_NAME).description(UPDATED_DESCRIPTION).active(UPDATED_ACTIVE); + + restSubjectMockMvc + .perform( + patch(ENTITY_API_URL_ID, partialUpdatedSubject.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(partialUpdatedSubject)) + ) + .andExpect(status().isOk()); + + // Validate the Subject in the database + + assertSameRepositoryCount(databaseSizeBeforeUpdate); + assertSubjectUpdatableFieldsEquals(partialUpdatedSubject, getPersistedSubject(partialUpdatedSubject)); + } + + @Test + @Transactional + void patchNonExistingSubject() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + subject.setId(longCount.incrementAndGet()); + + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restSubjectMockMvc + .perform( + patch(ENTITY_API_URL_ID, subjectDTO.getId()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(subjectDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithIdMismatchSubject() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + subject.setId(longCount.incrementAndGet()); + + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restSubjectMockMvc + .perform( + patch(ENTITY_API_URL_ID, longCount.incrementAndGet()) + .contentType("application/merge-patch+json") + .content(om.writeValueAsBytes(subjectDTO)) + ) + .andExpect(status().isBadRequest()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void patchWithMissingIdPathParamSubject() throws Exception { + long databaseSizeBeforeUpdate = getRepositoryCount(); + subject.setId(longCount.incrementAndGet()); + + // Create the Subject + SubjectDTO subjectDTO = subjectMapper.toDto(subject); + + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + restSubjectMockMvc + .perform(patch(ENTITY_API_URL).contentType("application/merge-patch+json").content(om.writeValueAsBytes(subjectDTO))) + .andExpect(status().isMethodNotAllowed()); + + // Validate the Subject in the database + assertSameRepositoryCount(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + void deleteSubject() throws Exception { + // Initialize the database + insertedSubject = subjectRepository.saveAndFlush(subject); + + long databaseSizeBeforeDelete = getRepositoryCount(); + + // Delete the subject + restSubjectMockMvc + .perform(delete(ENTITY_API_URL_ID, subject.getId()).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + // Validate the database contains one less item + assertDecrementedRepositoryCount(databaseSizeBeforeDelete); + } + + protected long getRepositoryCount() { + return subjectRepository.count(); + } + + protected void assertIncrementedRepositoryCount(long countBefore) { + assertThat(countBefore + 1).isEqualTo(getRepositoryCount()); + } + + protected void assertDecrementedRepositoryCount(long countBefore) { + assertThat(countBefore - 1).isEqualTo(getRepositoryCount()); + } + + protected void assertSameRepositoryCount(long countBefore) { + assertThat(countBefore).isEqualTo(getRepositoryCount()); + } + + protected Subject getPersistedSubject(Subject subject) { + return subjectRepository.findById(subject.getId()).orElseThrow(); + } + + protected void assertPersistedSubjectToMatchAllProperties(Subject expectedSubject) { + assertSubjectAllPropertiesEquals(expectedSubject, getPersistedSubject(expectedSubject)); + } + + protected void assertPersistedSubjectToMatchUpdatableProperties(Subject expectedSubject) { + assertSubjectAllUpdatablePropertiesEquals(expectedSubject, getPersistedSubject(expectedSubject)); + } +}