diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..be36c56 --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'body-max-line-length': [0, 'always'], + 'footer-max-line-length': [0, 'always'], + }, +}; diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f844960 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = tab +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false + +[*.yml] +indent_style = space + +[*.json] +indent_style = space diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..e56a295 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,83 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + ignorePatterns: ['.eslintrc.cjs', 'node_modules', 'coverage', 'src/exported/api/@types/i18n.d.ts'], + root: true, + overrides: [ + { + files: ['*.ts'], + plugins: ['@typescript-eslint', 'import'], + extends: [ + 'eslint:recommended', + 'plugin:@angular-eslint/recommended', + 'plugin:@angular-eslint/template/process-inline-templates', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:prettier/recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + ], + settings: { + 'import/resolver': { + typescript: true, + node: true, + }, + }, + rules: { + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unsafe-enum-comparison': 'off', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/unbound-method': 'off', + 'no-console': ['error', { allow: ['warn', 'error'] }], + 'prettier/prettier': ['error', { endOfLine: 'lf' }], + 'import/export': 'off', + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + groups: ['type', 'builtin', 'external', 'internal', ['parent', 'sibling', 'index']], + pathGroups: [ + { + pattern: '@(database|modules|templates|utils|src)/**', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: ['builtin'], + alphabetize: { + order: 'asc', + caseInsensitive: true, + }, + }, + ], + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'sith', + style: 'camelCase', + }, + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'sith', + style: 'kebab-case', + }, + ], + }, + }, + { + files: ['*.html'], + extends: ['plugin:@angular-eslint/template/recommended', 'plugin:@angular-eslint/template/accessibility'], + rules: {}, + }, + ], +}; diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index b8ecd8d..67cada0 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -2,31 +2,31 @@ ## Nos engagements -Dans le but de favoriser un environnement ouvert et accueillant, nous, en tant que contributeurs et mainteneurs nous engageons à faire de la participation à notre projet et à notre notre communauté une expérience sans harcèlement pour tous, indépendamment de l'âge, de la taille, du l'âge, la taille, le handicap, l'origine ethnique, les caractéristiques sexuelles, l'identité et l'expression de genre, niveau d'expérience, d'éducation, de statut socio-économique, de nationalité, d'apparence personnelle l'apparence personnelle, la race, la religion, l'identité et l'orientation sexuelles. +Dans le but de favoriser un environnement ouvert et accueillant, nous, en tant que contributeurs et mainteneurs nous engageons à faire de la participation à notre projet et à notre communauté une expérience sans harcèlement pour tous, indépendamment de l'âge, de la taille, d'un handicap, de l'origine ethnique, des caractéristiques sexuelles, de l'identité et l'expression de genre, du niveau d'expérience et d'éducation, du statut socio-économique, de la nationalité, de l'apparence personnelle, de la race, de la religion et de l'identité et l'orientation sexuelle. ## Nos normes Les exemples de comportements qui contribuent à un environnement positif pour notre communauté : -* Faire preuve d'empathie et de gentillesse envers les autres. -* Respecter les opinions, les points de vue et les expériences différentes. -* Émettre et accepter les commentaires constructifs -* Accepter la responsabilité et s'excuser auprès des personnes affectées par nos erreurs, et apprendre de l'expérience -* Se concentrer sur ce qui est le mieux non seulement pour nous en tant qu'individus, mais pour la communauté dans son ensemble +- Faire preuve d'empathie et de gentillesse envers les autres. +- Respecter les opinions, les points de vue et les expériences différentes. +- Émettre et accepter les commentaires constructifs +- Accepter la responsabilité et s'excuser auprès des personnes affectées par nos erreurs, et apprendre de l'expérience +- Se concentrer sur ce qui est le mieux non seulement pour nous en tant qu'individus, mais pour la communauté dans son ensemble Voici quelques exemples de comportements inacceptables : -* l'utilisation d'un langage ou d'images à caractère sexuel, et les attentions ou avances sexuelles. -* le trollage, les commentaires insultants ou désobligeants et les attaques personnelles ou politiques -* le harcèlement public ou privé -* la publication d'informations privées d'autrui, telles qu'une adresse physique ou électronique, sans leur permission explicite. -* toute autre conduite qui pourrait raisonnablement être considérée comme inappropriée dans un cadre professionnel. +- l'utilisation d'un langage ou d'images à caractère sexuel, et les attentions ou avances sexuelles. +- le trollage, les commentaires insultants ou désobligeants et les attaques personnelles ou politiques +- le harcèlement public ou privé +- la publication d'informations privées d'autrui, telles qu'une adresse physique ou électronique, sans leur permission explicite. +- toute autre conduite qui pourrait raisonnablement être considérée comme inappropriée dans un cadre professionnel. ## Nos responsabilités Les responsables de projet sont chargés de clarifier et d'appliquer nos normes de comportement acceptable et prendront des mesures correctives appropriées et équitables en réponse à tout cas de comportement inacceptable. -Les responsables du projet ont le droit et la responsabilité de supprimer, modifier ou rejeter commentaires, commits, code, éditions wiki, problèmes et autres contributions qui ne sont pas ne sont pas conformes au présent code de conduite, ou de bannir temporairement ou définitivement tout contributeur pour d'autres comportements qu'ils jugent inappropriés, menaçants, offensants ou nuisibles. +Les responsables du projet ont le droit et la responsabilité de supprimer, modifier ou rejeter commentaires, commits, code, éditions wiki, problèmes et autres contributions qui ne sont pas conformes au présent code de conduite, ou de bannir temporairement ou définitivement tout contributeur pour d'autres comportements qu'ils jugent inappropriés, menaçants, offensants ou nuisibles. ## Champ d'application @@ -34,7 +34,7 @@ Ce code de conduite s'applique dans tous les espaces communautaires, ainsi que l ## Application de la loi -Les cas d'abus, de harcèlement ou de tout autre comportement inacceptable peuvent être signalés aux responsables de la communauté chargés de faire respecter la loi. Toutes les plaintes seront examinées et feront l'objet d'une enquête rapide et équitable. +Les cas d'abus, de harcèlements et tous les autres comportements inacceptables peuvent être signalés aux responsables de la communauté chargés de faire respecter la loi. Toutes les plaintes seront examinées et feront l'objet d'une enquête rapide et équitable. Tous les responsables communautaires sont tenus de respecter la vie privée et la sécurité de la personne qui signale un incident. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 94b8b34..79cd9b0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,4 +1,5 @@ + # Contribuer au Sith 4 Premièrement, merci de prendre le temps de contribuer ! ❤️ @@ -13,6 +14,7 @@ Tout type de contributions sont encouragée et valorisée. Veuillez consulter la > - Mentioner le projet lors de réunion locales et parler-en à vos amis/collègues + ## Table des matières - [Code de conduite](#code-de-conduite) @@ -49,13 +51,14 @@ Nous nous occuperons alors du problème dans les plus brefs délais. ### Rapporter des Bugs + #### Avant de rapporter un bug Une bonne issue ne doit pas laisser les autres vous courir après afin d'obtenir davantage d'information. Ainsi, nous vous demandons d'enquêter attentivement, de collecter des informations et décrire le problème en détail dans votre rapport. Veuillez compléter les étapes suivantes à l'avance pour nous aider à résoudre le bug potentiel le plus rapidement possible. - Assurez-vous d'utiliser la dernière version. - Vérifiez si votre bug n'est pas en fait une erreur de votre côté, par exemple en utilisant des composants d'environnement/incompatibles (assurez-vous d'avoir lu la [documentation](https://github.com/ae-utbm/api/wiki). -Si vous recherchez de l'aide, vous pouvez consulter [cette section](#jai-une-question)). + Si vous recherchez de l'aide, vous pouvez consulter [cette section](#jai-une-question)). - Pour voir si d'autres utilisateurs ont expérimentés (et potentiellement déjà résolu) le même problème que vous rencontrez, vérifiez si il n'y a pas déjà un rapport de bug existant pour votre bug ou erreur dans le [bug tracker](https://github.com/ae-utbm/sith4/issues?q=is%3Aissue+is%3Aclosed) - Assurez-vous de rechercher sur internet (y compris Stack Overflow) pour voir si d'autres utilisateurs hors de la communauté GitHub ont discuté du problème. - Collectez des informations sur le bug : @@ -73,7 +76,7 @@ Nous utilisons les issues GitHub pour suivre les bugs et les erreurs. Si vous re - Ouvrez une [issue](https://github.com/ae-utbm/sith4/issues/new). (Comme nous ne pouvons pas être sûrs à ce stade de savoir si c'est un bug ou non, nous vous demandons de ne pas parler de bug et de ne pas ajouter de tag sur l'issue.) - Expliquer le comportement que vous attendez et le comportement réel. -- Veuillez fournir autant de contexte que possible et décrire les *étapes de reproduction* que quelqu'un d'autre peut suivre pour recréer le problème sur son propre ordinateur. Cela inclut généralement votre code. Pour de bons rapports de bugs, vous devez isoler le problème et créer un cas de test réduit. +- Veuillez fournir autant de contexte que possible et décrire les _étapes de reproduction_ que quelqu'un d'autre peut suivre pour recréer le problème sur son propre ordinateur. Cela inclut généralement votre code. Pour de bons rapports de bugs, vous devez isoler le problème et créer un cas de test réduit. - Si vous en avez la possibilité, incluez des captures d'écran et des vidéos qui montrent le problème. Une fois que c'est fait : @@ -89,6 +92,7 @@ Cette section vous guide Cette section vous guide tout au long de la soumission d'une suggestion d'amélioration pour le Sith 4, **incluant des fonctionnalités entièrement nouvelles et des améliorations mineures des fonctionnalités existantes**. Suivre ces directives aidera les mainteneurs et la communauté à comprendre votre suggestion et à trouver des suggestions connexes. + #### Avant de soumettre une amélioration - Assurez-vous que vous utilisez la dernière version. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c3a6e9d..cc93dd0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,8 +1,8 @@ name: 🐛 Rapport de bug description: Remplissez un rapport de bug -title: "[BUG] " -labels: ["type: bug", "status: triage"] -assignees: "developers-v4" +title: '[BUG] ' +labels: ['type: bug', 'status: triage'] +assignees: 'developers-v4' body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_report.yml b/.github/ISSUE_TEMPLATE/feature_report.yml index 2d963a9..03d2c6d 100644 --- a/.github/ISSUE_TEMPLATE/feature_report.yml +++ b/.github/ISSUE_TEMPLATE/feature_report.yml @@ -1,8 +1,8 @@ name: ✨ Suggestion d'amélioration description: Suggérez une idée pour le projet -title: "[FEATURE] " -labels: ["type: feature", "status: triage"] -assignees: "developers-v4" +title: '[FEATURE] ' +labels: ['type: feature', 'status: triage'] +assignees: 'developers-v4' body: - type: markdown attributes: @@ -37,4 +37,3 @@ body: options: - label: "J'accepte de suivre le code de conduite de ce projet" required: true - \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..889c469 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,32 @@ + + +- [ ] J'ai lu [le code de conduite]('https://github.com/ae-utbm/sith4/blob/main/.github/CODE_OF_CONDUCT.md'). + +## Ajouts + +- +- +- + +## Changements + +- +- +- + +## Fixes + +- +- +- + +## Autre informations + +- +- +- diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 0000000..a16d899 --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,30 @@ +name: Code Linting + +on: + workflow_call: + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '16.x' + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install dependencies + run: pnpm install + + - name: Lint Typescript & HTML + run: pnpm eslint "{src,test}/**/*.{ts,js,html}" + + - name: Lint SCSS + run: pnpm npx stylelint "{src,test}/**/*.scss" diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 0000000..f7c2a8e --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,37 @@ +name: Run tests + +on: + workflow_call: + workflow_dispatch: + +jobs: + unit-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '16.x' + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install dependencies + run: pnpm install + + - name: Run tests + run: pnpm ng test --watch false + + - name: Export coverage results + uses: actions/upload-artifact@v3 + with: + name: Coverage results + path: coverage + retention-days: 7 + + # todo: add e2e tests + # Should run on all OSes (Windows, Linux, macOS) diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml new file mode 100644 index 0000000..e2a7cc8 --- /dev/null +++ b/.github/workflows/update.yml @@ -0,0 +1,17 @@ +# https://docs.github.com/en/actions/using-workflows/reusing-workflows +name: PR/Push update + +on: + pull_request: + branches: [main, develop] + push: + branches: [main, develop] + +jobs: + execute-lint: + uses: ./.github/workflows/linting.yml + + execute-tests: + needs: execute-lint + if: ${{ needs.execute-lint.result == 'success' }} + uses: ./.github/workflows/testing.yml diff --git a/.gitignore b/.gitignore index 048ceea..c211708 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,46 @@ -# System Files +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# Compiled output +/dist +/tmp +/out-tsc +/bazel-out + +# Node +/node_modules +npm-debug.log +yarn-error.log + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# Miscellaneous +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files .DS_Store Thumbs.db + +# Eslint reports +eslint.json + +src/__old diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..cbd50c5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/exported"] + path = src/exported + url = https://github.com/ae-utbm/typings.git diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..5e563eb --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx --no-install commitlint --edit diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a333abc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +# ignore generated files +.angular +coverage +dist +temp +src/database/migrations +src/exported/api/@types/i18n.d.ts +pnpm-lock.yaml +package.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..e25d51d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,19 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "semi": true, + "printWidth": 120, + "useTabs": true, + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf", + "overrides": [ + { + "files": "*.json", + "options": { + "printWidth": 10, + "useTabs": false + } + } + ] +} diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..e09d7e5 --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,10 @@ +module.exports = { + extends: ['stylelint-config-standard-scss'], + plugins: ['stylelint-scss'], + overrides: [ + { + files: ['*.scss', '**/*.scss'], + customSyntax: 'postcss-scss', + }, + ], +}; diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..8e89685 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,19 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 + "recommendations": [ + "angular.ng-template", + "aaron-bond.better-comments", + "streetsidesoftware.code-spell-checker", + "exodiusstudios.comment-anchors", + "leonardssh.vscord", + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint", + "github.copilot", + "github.vscode-pull-request-github", + "eamodio.gitlens", + "chrisbibby.hide-node-modules", + "esbenp.prettier-vscode", + "yoavbls.pretty-ts-errors", + "pkief.material-icon-theme" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9b64eda --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,39 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Start", + "type": "node", + "request": "launch", + "runtimeExecutable": "pnpm", + "args": [ + "run", + "start" + ], + "console": "integratedTerminal" + }, + { + "name": "Run tests", + "type": "node", + "request": "launch", + "runtimeExecutable": "pnpm", + "args": [ + "run", + "test" + ], + "console": "integratedTerminal" + }, + { + "name": "Lint", + "type": "node", + "request": "launch", + "runtimeExecutable": "pnpm", + "args": [ + "run", + "lint" + ], + "console": "integratedTerminal" + } + ] +} diff --git a/README.md b/README.md index 915f9cf..f236790 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Sith v4 + [![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/XK9WfPsUFm) [![GitHub issues](https://img.shields.io/github/issues/ae-utbm/sith4?style=for-the-badge)](https://GitHub.com/ae-utbm/sith4/issues) -[![GitHub pull requests](https://img.shields.io/github/issues-pr/ae-utbm/sith4?style=for-the-badge)](https://GitHub.com/ae-utbm/sith4/issues) \ No newline at end of file +[![GitHub pull requests](https://img.shields.io/github/issues-pr/ae-utbm/sith4?style=for-the-badge)](https://GitHub.com/ae-utbm/sith4/issues) diff --git a/angular.json b/angular.json new file mode 100644 index 0000000..6dcf040 --- /dev/null +++ b/angular.json @@ -0,0 +1,121 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "sith": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "sith", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/sith", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": [ + "zone.js" + ], + "tsConfig": "tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-builders/custom-webpack:dev-server", + "configurations": { + "production": { + "browserTarget": "sith:build:production" + }, + "development": { + "browserTarget": "sith:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "sith:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": [ + "zone.js", + "zone.js/testing" + ], + "tsConfig": "tsconfig.spec.json", + "inlineStyleLanguage": "scss", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/app/styles/styles.scss" + ], + "scripts": [], + "karmaConfig": "karma.conf.js", + "codeCoverage": true + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": [ + "src/**/*.ts", + "src/**/*.html" + ] + } + } + } + } + }, + "cli": { + "analytics": false, + "schematicCollections": [ + "@angular-eslint/schematics" + ] + } +} diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000..c2d5fd3 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /src/assets/i18n/en-US.json + translation: /src/assets/i18n/%locale%.json diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..ab198df --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,47 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +process.env['CHROME_BIN'] = require('puppeteer').executablePath(); + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma'), + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false, // leave Jasmine Spec Runner output visible in browser + }, + jasmineHtmlReporter: { + suppressAll: true, // removes the duplicated traces + }, + coverageReporter: { + dir: require('path').join(__dirname, './coverage/sith'), + subdir: '.', + reporters: [{ type: 'html' }, { type: 'text-summary' }], + check: { + global: { + statements: 100, + lines: 100, + branches: 100, + functions: 100, + }, + }, + }, + reporters: ['progress', 'kjhtml'], + browsers: ['ChromeHeadless'], + restartOnFileChange: true, + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..4bf1f44 --- /dev/null +++ b/package.json @@ -0,0 +1,83 @@ +{ + "engines": { + "node": ">=18.0.0" + }, + "name": "sith", + "version": "4.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "lint": "ng lint", + "lint:report": "eslint src/app -f json -o ./eslint.json", + "lint:fix": "ng lint --fix", + "prettier": "prettier --write .", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "prepare": "husky install" + }, + "private": true, + "dependencies": { + "@ae_utbm/typings": "file:src/exported", + "@angular/animations": "^16.2.12", + "@angular/common": "^16.2.12", + "@angular/compiler": "^16.2.12", + "@angular/core": "^16.2.12", + "@angular/forms": "^16.2.12", + "@angular/platform-browser": "^16.2.12", + "@angular/platform-browser-dynamic": "^16.2.12", + "@angular/router": "^16.2.12", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "cropperjs": "^1.6.1", + "crypto-browserify": "^3.12.0", + "install": "^0.13.0", + "ng-hcaptcha": "^2.2.0", + "rxjs": "~7.8.1", + "stream-browserify": "^3.0.0", + "tslib": "^2.6.2", + "zone.js": "~0.13.3" + }, + "devDependencies": { + "@angular-builders/custom-webpack": "16.0.1", + "@angular-devkit/build-angular": "^16.2.10", + "@angular-eslint/builder": "16.2.0", + "@angular-eslint/eslint-plugin": "16.2.0", + "@angular-eslint/eslint-plugin-template": "16.2.0", + "@angular-eslint/schematics": "16.2.0", + "@angular-eslint/template-parser": "16.2.0", + "@angular/cli": "~16.2.10", + "@angular/compiler-cli": "^16.2.12", + "@commitlint/cli": "^17.8.1", + "@commitlint/config-conventional": "^17.8.1", + "@types/jasmine": "~4.3.6", + "@types/node": "^18.18.9", + "@typescript-eslint/eslint-plugin": "5.62.0", + "@typescript-eslint/parser": "5.62.0", + "eslint": "^8.53.0", + "eslint-config-prettier": "^8.10.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-html": "^7.1.0", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-prettier": "^4.2.1", + "husky": "^8.0.3", + "jasmine-core": "~4.5.0", + "karma": "~6.4.2", + "karma-chrome-launcher": "~3.1.1", + "karma-coverage": "^2.2.1", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.0.0", + "prettier": "^2.8.8", + "puppeteer": "^19.11.1", + "stylelint": "^15.11.0", + "stylelint-config-standard-scss": "^8.0.0", + "stylelint-scss": "^4.7.0", + "typescript": "~5.1.6" + }, + "browser": { + "fs": false, + "os": false, + "path": false, + "crypto": false + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..32a96fd --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,10845 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@ae_utbm/typings': + specifier: file:src/exported + version: file:src/exported + '@angular/animations': + specifier: ^16.2.12 + version: 16.2.12(@angular/core@16.2.12) + '@angular/common': + specifier: ^16.2.12 + version: 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@angular/compiler': + specifier: ^16.2.12 + version: 16.2.12(@angular/core@16.2.12) + '@angular/core': + specifier: ^16.2.12 + version: 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + '@angular/forms': + specifier: ^16.2.12 + version: 16.2.12(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12)(rxjs@7.8.1) + '@angular/platform-browser': + specifier: ^16.2.12 + version: 16.2.12(@angular/animations@16.2.12)(@angular/common@16.2.12)(@angular/core@16.2.12) + '@angular/platform-browser-dynamic': + specifier: ^16.2.12 + version: 16.2.12(@angular/common@16.2.12)(@angular/compiler@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12) + '@angular/router': + specifier: ^16.2.12 + version: 16.2.12(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12)(rxjs@7.8.1) + '@ngx-translate/core': + specifier: ^14.0.0 + version: 14.0.0(@angular/core@16.2.12)(rxjs@7.8.1) + '@ngx-translate/http-loader': + specifier: ^7.0.0 + version: 7.0.0(@angular/common@16.2.12)(@ngx-translate/core@14.0.0)(rxjs@7.8.1) + cropperjs: + specifier: ^1.6.1 + version: 1.6.1 + crypto-browserify: + specifier: ^3.12.0 + version: 3.12.0 + install: + specifier: ^0.13.0 + version: 0.13.0 + ng-hcaptcha: + specifier: ^2.2.0 + version: 2.2.0(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/forms@16.2.12) + rxjs: + specifier: ~7.8.1 + version: 7.8.1 + stream-browserify: + specifier: ^3.0.0 + version: 3.0.0 + tslib: + specifier: ^2.6.2 + version: 2.6.2 + zone.js: + specifier: ~0.13.3 + version: 0.13.3 + +devDependencies: + '@angular-builders/custom-webpack': + specifier: 16.0.1 + version: 16.0.1(@angular/compiler-cli@16.2.12)(@types/node@18.18.9)(karma@6.4.2)(typescript@5.1.6) + '@angular-devkit/build-angular': + specifier: ^16.2.10 + version: 16.2.10(@angular/compiler-cli@16.2.12)(@types/node@18.18.9)(karma@6.4.2)(typescript@5.1.6) + '@angular-eslint/builder': + specifier: 16.2.0 + version: 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@angular-eslint/eslint-plugin': + specifier: 16.2.0 + version: 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@angular-eslint/eslint-plugin-template': + specifier: 16.2.0 + version: 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@angular-eslint/schematics': + specifier: 16.2.0 + version: 16.2.0(@angular/cli@16.2.10)(eslint@8.53.0)(typescript@5.1.6) + '@angular-eslint/template-parser': + specifier: 16.2.0 + version: 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@angular/cli': + specifier: ~16.2.10 + version: 16.2.10 + '@angular/compiler-cli': + specifier: ^16.2.12 + version: 16.2.12(@angular/compiler@16.2.12)(typescript@5.1.6) + '@commitlint/cli': + specifier: ^17.8.1 + version: 17.8.1 + '@commitlint/config-conventional': + specifier: ^17.8.1 + version: 17.8.1 + '@types/jasmine': + specifier: ~4.3.6 + version: 4.3.6 + '@types/node': + specifier: ^18.18.9 + version: 18.18.9 + '@typescript-eslint/eslint-plugin': + specifier: 5.62.0 + version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.53.0)(typescript@5.1.6) + '@typescript-eslint/parser': + specifier: 5.62.0 + version: 5.62.0(eslint@8.53.0)(typescript@5.1.6) + eslint: + specifier: ^8.53.0 + version: 8.53.0 + eslint-config-prettier: + specifier: ^8.10.0 + version: 8.10.0(eslint@8.53.0) + eslint-import-resolver-typescript: + specifier: ^3.6.1 + version: 3.6.1(@typescript-eslint/parser@5.62.0)(eslint-plugin-import@2.29.0)(eslint@8.53.0) + eslint-plugin-html: + specifier: ^7.1.0 + version: 7.1.0 + eslint-plugin-import: + specifier: ^2.29.0 + version: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.53.0)(prettier@2.8.8) + husky: + specifier: ^8.0.3 + version: 8.0.3 + jasmine-core: + specifier: ~4.5.0 + version: 4.5.0 + karma: + specifier: ~6.4.2 + version: 6.4.2 + karma-chrome-launcher: + specifier: ~3.1.1 + version: 3.1.1 + karma-coverage: + specifier: ^2.2.1 + version: 2.2.1 + karma-jasmine: + specifier: ~5.1.0 + version: 5.1.0(karma@6.4.2) + karma-jasmine-html-reporter: + specifier: ~2.0.0 + version: 2.0.0(jasmine-core@4.5.0)(karma-jasmine@5.1.0)(karma@6.4.2) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + puppeteer: + specifier: ^19.11.1 + version: 19.11.1(typescript@5.1.6) + stylelint: + specifier: ^15.11.0 + version: 15.11.0(typescript@5.1.6) + stylelint-config-standard-scss: + specifier: ^8.0.0 + version: 8.0.0(postcss@8.4.31)(stylelint@15.11.0) + stylelint-scss: + specifier: ^4.7.0 + version: 4.7.0(stylelint@15.11.0) + typescript: + specifier: ~5.1.6 + version: 5.1.6 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@angular-builders/custom-webpack@16.0.1(@angular/compiler-cli@16.2.12)(@types/node@18.18.9)(karma@6.4.2)(typescript@5.1.6): + resolution: {integrity: sha512-C6INC8UOYDcp8LJwNhE0m66yp+nZX50JdgGI8oRn7fqw3gO58qhDgXrR/8BCrSeC8eOx8WxSuvBJ6u+9dozhyw==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/compiler-cli': ^16.0.0 + dependencies: + '@angular-devkit/architect': 0.1602.10(chokidar@3.5.3) + '@angular-devkit/build-angular': 16.2.10(@angular/compiler-cli@16.2.12)(@types/node@18.18.9)(karma@6.4.2)(typescript@5.1.6) + '@angular-devkit/core': 16.2.10(chokidar@3.5.3) + '@angular/compiler-cli': 16.2.12(@angular/compiler@16.2.12)(typescript@5.1.6) + lodash: 4.17.21 + ts-node: 10.9.1(@types/node@18.18.9)(typescript@5.1.6) + tsconfig-paths: 4.2.0 + webpack-merge: 5.10.0 + transitivePeerDependencies: + - '@angular/localize' + - '@angular/platform-server' + - '@angular/service-worker' + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - bufferutil + - canvas + - chokidar + - debug + - fibers + - html-webpack-plugin + - jest + - jest-environment-jsdom + - karma + - lightningcss + - ng-packagr + - node-sass + - protractor + - sass-embedded + - stylus + - sugarss + - supports-color + - tailwindcss + - typescript + - uglify-js + - utf-8-validate + - webpack-cli + dev: true + + /@angular-devkit/architect@0.1602.10(chokidar@3.5.3): + resolution: {integrity: sha512-FwemQXh3edqA/S6zPpsqKei5v7gt0R0WpjJoAJaz+FOpfDwij1fwnKr88XINY8xcefTcQaTDQxJZheJShA/hHw==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 16.2.10(chokidar@3.5.3) + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/build-angular@16.2.10(@angular/compiler-cli@16.2.12)(@types/node@18.18.9)(karma@6.4.2)(typescript@5.1.6): + resolution: {integrity: sha512-msB/qjIsAOySDxdU5DpcX2sWGUEJOFIO03O9+HbtLwf3NDfe74mFfejxuKlHJXIJdgpM2Zc948M6+618QKpUYA==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler-cli': ^16.0.0 + '@angular/localize': ^16.0.0 + '@angular/platform-server': ^16.0.0 + '@angular/service-worker': ^16.0.0 + jest: ^29.5.0 + jest-environment-jsdom: ^29.5.0 + karma: ^6.3.0 + ng-packagr: ^16.0.0 + protractor: ^7.0.0 + tailwindcss: ^2.0.0 || ^3.0.0 + typescript: '>=4.9.3 <5.2' + peerDependenciesMeta: + '@angular/localize': + optional: true + '@angular/platform-server': + optional: true + '@angular/service-worker': + optional: true + jest: + optional: true + jest-environment-jsdom: + optional: true + karma: + optional: true + ng-packagr: + optional: true + protractor: + optional: true + tailwindcss: + optional: true + dependencies: + '@ampproject/remapping': 2.2.1 + '@angular-devkit/architect': 0.1602.10(chokidar@3.5.3) + '@angular-devkit/build-webpack': 0.1602.10(chokidar@3.5.3)(webpack-dev-server@4.15.1)(webpack@5.88.2) + '@angular-devkit/core': 16.2.10(chokidar@3.5.3) + '@angular/compiler-cli': 16.2.12(@angular/compiler@16.2.12)(typescript@5.1.6) + '@babel/core': 7.22.9 + '@babel/generator': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.22.9) + '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) + '@babel/preset-env': 7.22.9(@babel/core@7.22.9) + '@babel/runtime': 7.22.6 + '@babel/template': 7.22.5 + '@discoveryjs/json-ext': 0.5.7 + '@ngtools/webpack': 16.2.10(@angular/compiler-cli@16.2.12)(typescript@5.1.6)(webpack@5.88.2) + '@vitejs/plugin-basic-ssl': 1.0.1(vite@4.4.7) + ansi-colors: 4.1.3 + autoprefixer: 10.4.14(postcss@8.4.31) + babel-loader: 9.1.3(@babel/core@7.22.9)(webpack@5.88.2) + babel-plugin-istanbul: 6.1.1 + browserslist: 4.22.1 + chokidar: 3.5.3 + copy-webpack-plugin: 11.0.0(webpack@5.88.2) + critters: 0.0.20 + css-loader: 6.8.1(webpack@5.88.2) + esbuild-wasm: 0.18.17 + fast-glob: 3.3.1 + guess-parser: 0.4.22(typescript@5.1.6) + https-proxy-agent: 5.0.1 + inquirer: 8.2.4 + jsonc-parser: 3.2.0 + karma: 6.4.2 + karma-source-map-support: 1.4.0 + less: 4.1.3 + less-loader: 11.1.0(less@4.1.3)(webpack@5.88.2) + license-webpack-plugin: 4.0.2(webpack@5.88.2) + loader-utils: 3.2.1 + magic-string: 0.30.1 + mini-css-extract-plugin: 2.7.6(webpack@5.88.2) + mrmime: 1.0.1 + open: 8.4.2 + ora: 5.4.1 + parse5-html-rewriting-stream: 7.0.0 + picomatch: 2.3.1 + piscina: 4.0.0 + postcss: 8.4.31 + postcss-loader: 7.3.3(postcss@8.4.31)(typescript@5.1.6)(webpack@5.88.2) + resolve-url-loader: 5.0.0 + rxjs: 7.8.1 + sass: 1.64.1 + sass-loader: 13.3.2(sass@1.64.1)(webpack@5.88.2) + semver: 7.5.4 + source-map-loader: 4.0.1(webpack@5.88.2) + source-map-support: 0.5.21 + terser: 5.19.2 + text-table: 0.2.0 + tree-kill: 1.2.2 + tslib: 2.6.1 + typescript: 5.1.6 + vite: 4.4.7(@types/node@18.18.9)(less@4.1.3)(sass@1.64.1)(terser@5.19.2) + webpack: 5.88.2(esbuild@0.18.17) + webpack-dev-middleware: 6.1.1(webpack@5.88.2) + webpack-dev-server: 4.15.1(webpack@5.88.2) + webpack-merge: 5.9.0 + webpack-subresource-integrity: 5.1.0(webpack@5.88.2) + optionalDependencies: + esbuild: 0.18.17 + transitivePeerDependencies: + - '@swc/core' + - '@types/node' + - bufferutil + - canvas + - debug + - fibers + - html-webpack-plugin + - lightningcss + - node-sass + - sass-embedded + - stylus + - sugarss + - supports-color + - uglify-js + - utf-8-validate + - webpack-cli + dev: true + + /@angular-devkit/build-webpack@0.1602.10(chokidar@3.5.3)(webpack-dev-server@4.15.1)(webpack@5.88.2): + resolution: {integrity: sha512-H7HiFKbZl/xVxpr1RH05SGawTpA1417wvr2nFGRu2OiePd0lPr6pIhcq8F8gt7JcA8yZKKaqjn2gU+6um2MFLg==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + webpack: ^5.30.0 + webpack-dev-server: ^4.0.0 + dependencies: + '@angular-devkit/architect': 0.1602.10(chokidar@3.5.3) + rxjs: 7.8.1 + webpack: 5.88.2(esbuild@0.18.17) + webpack-dev-server: 4.15.1(webpack@5.88.2) + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/core@16.2.10(chokidar@3.5.3): + resolution: {integrity: sha512-eo7suLDjyu5bSlEr4TluYkFm4v2PVLSAPgnau8XHHlN5Yg4P/BZ00ve7LA7C9S1gzRSCrxQhK5ki4rnoFTo5zg==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^3.5.2 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + chokidar: 3.5.3 + jsonc-parser: 3.2.0 + picomatch: 2.3.1 + rxjs: 7.8.1 + source-map: 0.7.4 + dev: true + + /@angular-devkit/schematics@16.2.10: + resolution: {integrity: sha512-UCfPJKVNekb21bWRbzyx81tfHN3x8vU4ZMX/VA6xALg//QalMB7NOkkXBAssthnLastkyzkUtlvApTp2+R+EkQ==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 16.2.10(chokidar@3.5.3) + jsonc-parser: 3.2.0 + magic-string: 0.30.1 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-eslint/builder@16.2.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-SZjXOi3YIjuX2CocuRsR2QH6k1ca9lRO6IMm0YIYMmBPFCRP2KFHkL6aQnXM6DSaymQNN2TXfpuvUd45NxhU1w==} + peerDependencies: + eslint: ^7.20.0 || ^8.0.0 + typescript: '*' + dependencies: + '@nx/devkit': 16.5.1(nx@16.5.1) + eslint: 8.53.0 + nx: 16.5.1 + typescript: 5.1.6 + transitivePeerDependencies: + - '@swc-node/register' + - '@swc/core' + - debug + dev: true + + /@angular-eslint/bundled-angular-compiler@16.2.0: + resolution: {integrity: sha512-ct9orDYxkMl2+uvM7UBfgV28Dq57V4dEs+Drh7cD673JIMa6sXbgmd0QEtm8W3cmyK/jcTzmuoufxbH7hOxd6g==} + dev: true + + /@angular-eslint/eslint-plugin-template@16.2.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-YFdQ6hHX6NlQj0lfogZwfyKjU8pqkJU+Zsk0ehjlXP8VfKFVmDeQT5/Xr6Df9C8pveC3hvq6Jgd8vo67S9Enxg==} + peerDependencies: + eslint: ^7.20.0 || ^8.0.0 + typescript: '*' + dependencies: + '@angular-eslint/bundled-angular-compiler': 16.2.0 + '@angular-eslint/utils': 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@typescript-eslint/type-utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + aria-query: 5.3.0 + axobject-query: 3.2.1 + eslint: 8.53.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@angular-eslint/eslint-plugin@16.2.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-zdiAIox1T+B71HL+A8m+1jWdU34nvPGLhCRw/uZNwHzknsF4tYzNQ9W7T/SC/g/2s1yT2yNosEVNJSGSFvunJg==} + peerDependencies: + eslint: ^7.20.0 || ^8.0.0 + typescript: '*' + dependencies: + '@angular-eslint/utils': 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + eslint: 8.53.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@angular-eslint/schematics@16.2.0(@angular/cli@16.2.10)(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-2JUVR7hAKx37mgWeDjvyWEMH5uSeeksYuaQT5wwlgIzgrO4BNFuqs6Rgyp2jiYa7BFMX/qHULSa+bSq5J5ceEA==} + peerDependencies: + '@angular/cli': '>= 16.0.0 < 17.0.0' + dependencies: + '@angular-eslint/eslint-plugin': 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@angular-eslint/eslint-plugin-template': 16.2.0(eslint@8.53.0)(typescript@5.1.6) + '@angular/cli': 16.2.10 + '@nx/devkit': 16.5.1(nx@16.5.1) + ignore: 5.2.4 + nx: 16.5.1 + strip-json-comments: 3.1.1 + tmp: 0.2.1 + transitivePeerDependencies: + - '@swc-node/register' + - '@swc/core' + - debug + - eslint + - supports-color + - typescript + dev: true + + /@angular-eslint/template-parser@16.2.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-v2jVKTy2wN7iM9nHpBkxLn2wfL8jSl4IlPrXThIqj8No2VHtpLQZPKuXbGPUXQX05VS2Mj5feScQ36ZVGS8Rbw==} + peerDependencies: + eslint: ^7.20.0 || ^8.0.0 + typescript: '*' + dependencies: + '@angular-eslint/bundled-angular-compiler': 16.2.0 + eslint: 8.53.0 + eslint-scope: 7.2.2 + typescript: 5.1.6 + dev: true + + /@angular-eslint/utils@16.2.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-NxMRwnlIgzmbJQfWkfd9y3Sz0hzjFdK5LH44i+3D5NhpPdZ6SzwHAjMYWoYsmmNQX5tlDXoicYF9Mz9Wz8DJ/A==} + peerDependencies: + eslint: ^7.20.0 || ^8.0.0 + typescript: '*' + dependencies: + '@angular-eslint/bundled-angular-compiler': 16.2.0 + '@typescript-eslint/utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + eslint: 8.53.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@angular/animations@16.2.12(@angular/core@16.2.12): + resolution: {integrity: sha512-MD0ElviEfAJY8qMOd6/jjSSvtqER2RDAi0lxe6EtUacC1DHCYkaPrKW4vLqY+tmZBg1yf+6n+uS77pXcHHcA3w==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/core': 16.2.12 + dependencies: + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + tslib: 2.6.2 + dev: false + + /@angular/cli@16.2.10: + resolution: {integrity: sha512-zDqlD+rXFuYZP169c2v35HkMbkchVCft5sS+VpoCCgYTk2rwxpeYkjJ8DQZztZJZRXQ+EMpkv/TubswmDro2zA==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + dependencies: + '@angular-devkit/architect': 0.1602.10(chokidar@3.5.3) + '@angular-devkit/core': 16.2.10(chokidar@3.5.3) + '@angular-devkit/schematics': 16.2.10 + '@schematics/angular': 16.2.10 + '@yarnpkg/lockfile': 1.1.0 + ansi-colors: 4.1.3 + ini: 4.1.1 + inquirer: 8.2.4 + jsonc-parser: 3.2.0 + npm-package-arg: 10.1.0 + npm-pick-manifest: 8.0.1 + open: 8.4.2 + ora: 5.4.1 + pacote: 15.2.0 + resolve: 1.22.2 + semver: 7.5.4 + symbol-observable: 4.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - bluebird + - chokidar + - supports-color + dev: true + + /@angular/common@16.2.12(@angular/core@16.2.12)(rxjs@7.8.1): + resolution: {integrity: sha512-B+WY/cT2VgEaz9HfJitBmgdk4I333XG/ybC98CMC4Wz8E49T8yzivmmxXB3OD6qvjcOB6ftuicl6WBqLbZNg2w==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/core': 16.2.12 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + rxjs: 7.8.1 + tslib: 2.6.2 + dev: false + + /@angular/compiler-cli@16.2.12(@angular/compiler@16.2.12)(typescript@5.1.6): + resolution: {integrity: sha512-pWSrr152562ujh6lsFZR8NfNc5Ljj+zSTQO44DsuB0tZjwEpnRcjJEgzuhGXr+CoiBf+jTSPZKemtSktDk5aaA==} + engines: {node: ^16.14.0 || >=18.10.0} + hasBin: true + peerDependencies: + '@angular/compiler': 16.2.12 + typescript: '>=4.9.3 <5.2' + dependencies: + '@angular/compiler': 16.2.12(@angular/core@16.2.12) + '@babel/core': 7.23.2 + '@jridgewell/sourcemap-codec': 1.4.15 + chokidar: 3.5.3 + convert-source-map: 1.9.0 + reflect-metadata: 0.1.13 + semver: 7.5.4 + tslib: 2.6.2 + typescript: 5.1.6 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@angular/compiler@16.2.12(@angular/core@16.2.12): + resolution: {integrity: sha512-6SMXUgSVekGM7R6l1Z9rCtUGtlg58GFmgbpMCsGf+VXxP468Njw8rjT2YZkf5aEPxEuRpSHhDYjqz7n14cwCXQ==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/core': 16.2.12 + peerDependenciesMeta: + '@angular/core': + optional: true + dependencies: + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + tslib: 2.6.2 + + /@angular/core@16.2.12(rxjs@7.8.1)(zone.js@0.13.3): + resolution: {integrity: sha512-GLLlDeke/NjroaLYOks0uyzFVo6HyLl7VOm0K1QpLXnYvW63W9Ql/T3yguRZa7tRkOAeFZ3jw+1wnBD4O8MoUA==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + rxjs: ^6.5.3 || ^7.4.0 + zone.js: ~0.13.0 + dependencies: + rxjs: 7.8.1 + tslib: 2.6.2 + zone.js: 0.13.3 + + /@angular/forms@16.2.12(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12)(rxjs@7.8.1): + resolution: {integrity: sha512-1Eao89hlBgLR3v8tU91vccn21BBKL06WWxl7zLpQmG6Hun+2jrThgOE4Pf3os4fkkbH4Apj0tWL2fNIWe/blbw==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/common': 16.2.12 + '@angular/core': 16.2.12 + '@angular/platform-browser': 16.2.12 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/common': 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + '@angular/platform-browser': 16.2.12(@angular/animations@16.2.12)(@angular/common@16.2.12)(@angular/core@16.2.12) + rxjs: 7.8.1 + tslib: 2.6.2 + dev: false + + /@angular/platform-browser-dynamic@16.2.12(@angular/common@16.2.12)(@angular/compiler@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12): + resolution: {integrity: sha512-ya54jerNgreCVAR278wZavwjrUWImMr2F8yM5n9HBvsMBbFaAQ83anwbOEiHEF2BlR+gJiEBLfpuPRMw20pHqw==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/common': 16.2.12 + '@angular/compiler': 16.2.12 + '@angular/core': 16.2.12 + '@angular/platform-browser': 16.2.12 + dependencies: + '@angular/common': 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@angular/compiler': 16.2.12(@angular/core@16.2.12) + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + '@angular/platform-browser': 16.2.12(@angular/animations@16.2.12)(@angular/common@16.2.12)(@angular/core@16.2.12) + tslib: 2.6.2 + dev: false + + /@angular/platform-browser@16.2.12(@angular/animations@16.2.12)(@angular/common@16.2.12)(@angular/core@16.2.12): + resolution: {integrity: sha512-NnH7ju1iirmVEsUq432DTm0nZBGQsBrU40M3ZeVHMQ2subnGiyUs3QyzDz8+VWLL/T5xTxWLt9BkDn65vgzlIQ==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/animations': 16.2.12 + '@angular/common': 16.2.12 + '@angular/core': 16.2.12 + peerDependenciesMeta: + '@angular/animations': + optional: true + dependencies: + '@angular/animations': 16.2.12(@angular/core@16.2.12) + '@angular/common': 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + tslib: 2.6.2 + dev: false + + /@angular/router@16.2.12(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12)(rxjs@7.8.1): + resolution: {integrity: sha512-aU6QnYSza005V9P3W6PpkieL56O0IHps96DjqI1RS8yOJUl3THmokqYN4Fm5+HXy4f390FN9i6ftadYQDKeWmA==} + engines: {node: ^16.14.0 || >=18.10.0} + peerDependencies: + '@angular/common': 16.2.12 + '@angular/core': 16.2.12 + '@angular/platform-browser': 16.2.12 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/common': 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + '@angular/platform-browser': 16.2.12(@angular/animations@16.2.12)(@angular/common@16.2.12)(@angular/core@16.2.12) + rxjs: 7.8.1 + tslib: 2.6.2 + dev: false + + /@assemblyscript/loader@0.10.1: + resolution: {integrity: sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==} + dev: true + + /@babel/code-frame@7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.20 + chalk: 2.4.2 + dev: true + + /@babel/compat-data@7.23.3: + resolution: {integrity: sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.22.9: + resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.22.9 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.22.9) + '@babel/helpers': 7.23.2 + '@babel/parser': 7.23.3 + '@babel/template': 7.22.5 + '@babel/traverse': 7.23.3 + '@babel/types': 7.23.3 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/core@7.23.2: + resolution: {integrity: sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.3 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.2) + '@babel/helpers': 7.23.2 + '@babel/parser': 7.23.3 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.3 + '@babel/types': 7.23.3 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/core@7.23.3: + resolution: {integrity: sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.3 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.3) + '@babel/helpers': 7.23.2 + '@babel/parser': 7.23.3 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.3 + '@babel/types': 7.23.3 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.22.9: + resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + jsesc: 2.5.2 + dev: true + + /@babel/generator@7.23.3: + resolution: {integrity: sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + jsesc: 2.5.2 + dev: true + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: + resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-compilation-targets@7.22.15: + resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.3 + '@babel/helper-validator-option': 7.22.15 + browserslist: 4.22.1 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.22.9): + resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.22.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + dev: true + + /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.22.9): + resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + regexpu-core: 5.3.2 + semver: 6.3.1 + dev: true + + /@babel/helper-define-polyfill-provider@0.4.3(@babel/core@7.22.9): + resolution: {integrity: sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-member-expression-to-functions@7.23.0: + resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.2): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.3): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.3 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-optimise-call-expression@7.22.5: + resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.22.9): + resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-wrap-function': 7.22.20 + dev: true + + /@babel/helper-replace-supers@7.22.20(@babel/core@7.22.9): + resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.22.5: + resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-wrap-function@7.22.20: + resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-function-name': 7.23.0 + '@babel/template': 7.22.15 + '@babel/types': 7.23.3 + dev: true + + /@babel/helpers@7.23.2: + resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.3 + '@babel/types': 7.23.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.23.3: + resolution: {integrity: sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.3 + dev: true + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-transform-optional-chaining': 7.23.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.22.9): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.9): + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + dev: true + + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.22.9): + resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} + engines: {node: '>=4'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.9): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.9): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.22.9): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.22.9): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.9): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.9): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.22.9): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.9): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.22.9): + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-async-generator-functions@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-59GsVNavGxAXCDDbakWSMJhajASb4kBCqDjqJsv+p5nKdbz7istmZ3HrX3L2LuiI80+zsOADCvooqQH3qGCucQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-block-scoping@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-QPZxHrThbQia7UdvfpaRRlq/J9ciz1J4go0k+lPBXbgaNeY7IQrBj/9ceWjvMMI07/ZBzHl/F0R/2K0qH7jCVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-class-static-block@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-PENDVxdr7ZxKPyi5Ffc0LjXdnJyrJxyqF5T5YjlVg4a0VFfQHW0r8iAtRiDXkfHlu1wwcvdtnndGYIeJLSuRMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-classes@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-FGEQmugvAEu2QtgtU0uTASXevfLMFfBeVCIIdcQhn/uBQsMTjBajdnAtanQlOcuihWh10PZ7+HWvc7NtBwP74w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + + /@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.22.15 + dev: true + + /@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-dynamic-import@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-vTG+cTGxPFou12Rj7ll+eD5yWeNl5/8xvQvF08y5Gv3v4mZQoyFf8/n9zg4q5vvCWt5jmgymfzMAldO7orBn7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-export-namespace-from@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-yCLhW34wpJWRdTxxWtFZASJisihrfyMOTOQexhVzA78jlU+dH7Dw+zQgcPepQ5F3C6bAIiblZZ+qBggJdHiBAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-for-of@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-function-name@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-json-strings@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-H9Ej2OiISIZowZHaBwF0tsJOih1PftXJtE8EWqlEIwpc7LMTGq0rPOrywKLQ4nefzx8/HMR0D3JGXoMHYvhi0A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-literals@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-logical-assignment-operators@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-+pD5ZbxofyOygEp+zZAfujY2ShNCXRpDRIPOiBmTO693hhyOEteZgl876Xs9SAHPQpcV0vz8LvA/T+w8AzyX8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-new-target@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-nullish-coalescing-operator@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-xzg24Lnld4DYIdysyf07zJ1P+iIfJpxtVFOzX4g+bsJ3Ng5Le7rXx9KwqKzuyaUeRnt+I1EICwQITqc0E2PmpA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-numeric-separator@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-s9GO7fIBi/BLsZ0v3Rftr6Oe4t0ctJ8h4CCXfPoEJwmvAPMyNrfkOOJzm6b9PX9YXcCJWWQd/sBF/N26eBiMVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-object-rest-spread@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-VxHt0ANkDmu8TANdE9Kc0rndo/ccsmfe2Cx2y5sI4hu3AukHQ5wAu4cM7j3ba8B9548ijVyclBU+nuDQftZsog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.23.3 + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-object-super@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-optional-catch-binding@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-LxYSb0iLjUamfm7f1D7GpiS4j0UAC8AOiehnsGAP8BEsIX8EOi3qV6bbctw8M7ZvLtcoZfZX5Z7rN9PlWk0m5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-optional-chaining@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-zvL8vIfIUgMccIAK1lxjvNv572JHFJIKb4MWBz5OGdBQA0fB0Xluix5rmOby48exiJc987neOmP/m9Fnpkz3Tg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-parameters@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-private-property-in-object@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-a5m2oLNFyje2e/rGKjVfAELTVI5mbA0FeZpBnkOWWV7eSmKQ+T/XW0Vf+29ScLzSxX+rnsarvU0oie/4m6hkxA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) + dev: true + + /@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + regenerator-transform: 0.15.2 + dev: true + + /@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-runtime@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.6(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.22.9) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-spread@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true + + /@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.22.9): + resolution: {integrity: sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/preset-env@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.23.3 + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.15 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-async-generator-functions': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoping': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-class-static-block': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-classes': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-dynamic-import': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-export-namespace-from': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-for-of': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-json-strings': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-logical-assignment-operators': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-modules-systemjs': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-numeric-separator': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-object-rest-spread': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-optional-catch-binding': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-optional-chaining': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-private-property-in-object': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.22.9) + '@babel/preset-modules': 0.1.6(@babel/core@7.22.9) + '@babel/types': 7.23.3 + babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.6(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.22.9) + core-js-compat: 3.33.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.6(@babel/core@7.22.9): + resolution: {integrity: sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.22.9) + '@babel/types': 7.23.3 + esutils: 2.0.3 + dev: true + + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true + + /@babel/runtime@7.22.6: + resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: true + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.3 + '@babel/types': 7.23.3 + dev: true + + /@babel/template@7.22.5: + resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.3 + '@babel/types': 7.23.3 + dev: true + + /@babel/traverse@7.23.3: + resolution: {integrity: sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.3 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.3 + '@babel/types': 7.23.3 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.23.3: + resolution: {integrity: sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + dev: true + + /@commitlint/cli@17.8.1: + resolution: {integrity: sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg==} + engines: {node: '>=v14'} + hasBin: true + dependencies: + '@commitlint/format': 17.8.1 + '@commitlint/lint': 17.8.1 + '@commitlint/load': 17.8.1 + '@commitlint/read': 17.8.1 + '@commitlint/types': 17.8.1 + execa: 5.1.1 + lodash.isfunction: 3.0.9 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + + /@commitlint/config-conventional@17.8.1: + resolution: {integrity: sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg==} + engines: {node: '>=v14'} + dependencies: + conventional-changelog-conventionalcommits: 6.1.0 + dev: true + + /@commitlint/config-validator@17.8.1: + resolution: {integrity: sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.8.1 + ajv: 8.12.0 + dev: true + + /@commitlint/ensure@17.8.1: + resolution: {integrity: sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + dev: true + + /@commitlint/execute-rule@17.8.1: + resolution: {integrity: sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ==} + engines: {node: '>=v14'} + dev: true + + /@commitlint/format@17.8.1: + resolution: {integrity: sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.8.1 + chalk: 4.1.2 + dev: true + + /@commitlint/is-ignored@17.8.1: + resolution: {integrity: sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.8.1 + semver: 7.5.4 + dev: true + + /@commitlint/lint@17.8.1: + resolution: {integrity: sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/is-ignored': 17.8.1 + '@commitlint/parse': 17.8.1 + '@commitlint/rules': 17.8.1 + '@commitlint/types': 17.8.1 + dev: true + + /@commitlint/load@17.8.1: + resolution: {integrity: sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/config-validator': 17.8.1 + '@commitlint/execute-rule': 17.8.1 + '@commitlint/resolve-extends': 17.8.1 + '@commitlint/types': 17.8.1 + '@types/node': 20.5.1 + chalk: 4.1.2 + cosmiconfig: 8.3.6(typescript@5.1.6) + cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@5.2.2) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + resolve-from: 5.0.0 + ts-node: 10.9.1(@types/node@18.18.9)(typescript@5.1.6) + typescript: 5.2.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + dev: true + + /@commitlint/message@17.8.1: + resolution: {integrity: sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA==} + engines: {node: '>=v14'} + dev: true + + /@commitlint/parse@17.8.1: + resolution: {integrity: sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/types': 17.8.1 + conventional-changelog-angular: 6.0.0 + conventional-commits-parser: 4.0.0 + dev: true + + /@commitlint/read@17.8.1: + resolution: {integrity: sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/top-level': 17.8.1 + '@commitlint/types': 17.8.1 + fs-extra: 11.1.1 + git-raw-commits: 2.0.11 + minimist: 1.2.8 + dev: true + + /@commitlint/resolve-extends@17.8.1: + resolution: {integrity: sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/config-validator': 17.8.1 + '@commitlint/types': 17.8.1 + import-fresh: 3.3.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + dev: true + + /@commitlint/rules@17.8.1: + resolution: {integrity: sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA==} + engines: {node: '>=v14'} + dependencies: + '@commitlint/ensure': 17.8.1 + '@commitlint/message': 17.8.1 + '@commitlint/to-lines': 17.8.1 + '@commitlint/types': 17.8.1 + execa: 5.1.1 + dev: true + + /@commitlint/to-lines@17.8.1: + resolution: {integrity: sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA==} + engines: {node: '>=v14'} + dev: true + + /@commitlint/top-level@17.8.1: + resolution: {integrity: sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA==} + engines: {node: '>=v14'} + dependencies: + find-up: 5.0.0 + dev: true + + /@commitlint/types@17.8.1: + resolution: {integrity: sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ==} + engines: {node: '>=v14'} + dependencies: + chalk: 4.1.2 + dev: true + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@csstools/css-parser-algorithms@2.3.2(@csstools/css-tokenizer@2.2.1): + resolution: {integrity: sha512-sLYGdAdEY2x7TSw9FtmdaTrh2wFtRJO5VMbBrA8tEqEod7GEggFmxTSK9XqExib3yMuYNcvcTdCZIP6ukdjAIA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-tokenizer': ^2.2.1 + dependencies: + '@csstools/css-tokenizer': 2.2.1 + dev: true + + /@csstools/css-tokenizer@2.2.1: + resolution: {integrity: sha512-Zmsf2f/CaEPWEVgw29odOj+WEVoiJy9s9NOv5GgNY9mZ1CZ7394By6wONrONrTsnNDv6F9hR02nvFihrGVGHBg==} + engines: {node: ^14 || ^16 || >=18} + dev: true + + /@csstools/media-query-list-parser@2.1.5(@csstools/css-parser-algorithms@2.3.2)(@csstools/css-tokenizer@2.2.1): + resolution: {integrity: sha512-IxVBdYzR8pYe89JiyXQuYk4aVVoCPhMJkz6ElRwlVysjwURTsTk/bmY/z4FfeRE+CRBMlykPwXEVUg8lThv7AQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-parser-algorithms': ^2.3.2 + '@csstools/css-tokenizer': ^2.2.1 + dependencies: + '@csstools/css-parser-algorithms': 2.3.2(@csstools/css-tokenizer@2.2.1) + '@csstools/css-tokenizer': 2.2.1 + dev: true + + /@csstools/selector-specificity@3.0.0(postcss-selector-parser@6.0.13): + resolution: {integrity: sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.13 + dependencies: + postcss-selector-parser: 6.0.13 + dev: true + + /@discoveryjs/json-ext@0.5.7: + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + dev: true + + /@esbuild/android-arm64@0.18.17: + resolution: {integrity: sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.17: + resolution: {integrity: sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.17: + resolution: {integrity: sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.17: + resolution: {integrity: sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.17: + resolution: {integrity: sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.17: + resolution: {integrity: sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.17: + resolution: {integrity: sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.17: + resolution: {integrity: sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.17: + resolution: {integrity: sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.17: + resolution: {integrity: sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.17: + resolution: {integrity: sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.17: + resolution: {integrity: sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.17: + resolution: {integrity: sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.17: + resolution: {integrity: sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.17: + resolution: {integrity: sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.17: + resolution: {integrity: sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.17: + resolution: {integrity: sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.17: + resolution: {integrity: sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.17: + resolution: {integrity: sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.17: + resolution: {integrity: sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.17: + resolution: {integrity: sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.17: + resolution: {integrity: sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.53.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.53.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.3: + resolution: {integrity: sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.23.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.53.0: + resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@gar/promisify@1.1.3: + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + dev: true + + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@leichtgewicht/ip-codec@2.0.4: + resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} + dev: true + + /@ngtools/webpack@16.2.10(@angular/compiler-cli@16.2.12)(typescript@5.1.6)(webpack@5.88.2): + resolution: {integrity: sha512-XAVn59zP3ztuKDtw92Xc9+64RK4u4c9g8y5GgtjIWeOwgNXl8bYhAo3uTZzrSrOu96DFZGjsmghFab/7/C2pDg==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler-cli': ^16.0.0 + typescript: '>=4.9.3 <5.2' + webpack: ^5.54.0 + dependencies: + '@angular/compiler-cli': 16.2.12(@angular/compiler@16.2.12)(typescript@5.1.6) + typescript: 5.1.6 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /@ngx-translate/core@14.0.0(@angular/core@16.2.12)(rxjs@7.8.1): + resolution: {integrity: sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==} + peerDependencies: + '@angular/core': '>=13.0.0' + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + rxjs: 7.8.1 + tslib: 2.6.2 + dev: false + + /@ngx-translate/http-loader@7.0.0(@angular/common@16.2.12)(@ngx-translate/core@14.0.0)(rxjs@7.8.1): + resolution: {integrity: sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==} + peerDependencies: + '@angular/common': '>=13.0.0' + '@ngx-translate/core': '>=14.0.0' + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/common': 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@ngx-translate/core': 14.0.0(@angular/core@16.2.12)(rxjs@7.8.1) + rxjs: 7.8.1 + tslib: 2.6.2 + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@npmcli/fs@2.1.2: + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.5.4 + dev: true + + /@npmcli/fs@3.1.0: + resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + semver: 7.5.4 + dev: true + + /@npmcli/git@4.1.0: + resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/promise-spawn': 6.0.2 + lru-cache: 7.18.3 + npm-pick-manifest: 8.0.1 + proc-log: 3.0.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.5.4 + which: 3.0.1 + transitivePeerDependencies: + - bluebird + dev: true + + /@npmcli/installed-package-contents@2.0.2: + resolution: {integrity: sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + npm-bundled: 3.0.0 + npm-normalize-package-bin: 3.0.1 + dev: true + + /@npmcli/move-file@2.0.1: + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: true + + /@npmcli/node-gyp@3.0.0: + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /@npmcli/promise-spawn@6.0.2: + resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + which: 3.0.1 + dev: true + + /@npmcli/run-script@6.0.2: + resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/node-gyp': 3.0.0 + '@npmcli/promise-spawn': 6.0.2 + node-gyp: 9.4.1 + read-package-json-fast: 3.0.2 + which: 3.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /@nrwl/devkit@16.5.1(nx@16.5.1): + resolution: {integrity: sha512-NB+DE/+AFJ7lKH/WBFyatJEhcZGj25F24ncDkwjZ6MzEiSOGOJS0LaV/R+VUsmS5EHTPXYOpn3zHWWAcJhyOmA==} + dependencies: + '@nx/devkit': 16.5.1(nx@16.5.1) + transitivePeerDependencies: + - nx + dev: true + + /@nrwl/tao@16.5.1: + resolution: {integrity: sha512-x+gi/fKdM6uQNIti9exFlm3V5LBP3Y8vOEziO42HdOigyrXa0S0HD2WMpccmp6PclYKhwEDUjKJ39xh5sdh4Ig==} + hasBin: true + dependencies: + nx: 16.5.1 + transitivePeerDependencies: + - '@swc-node/register' + - '@swc/core' + - debug + dev: true + + /@nx/devkit@16.5.1(nx@16.5.1): + resolution: {integrity: sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==} + peerDependencies: + nx: '>= 15 <= 17' + dependencies: + '@nrwl/devkit': 16.5.1(nx@16.5.1) + ejs: 3.1.9 + ignore: 5.2.4 + nx: 16.5.1 + semver: 7.5.3 + tmp: 0.2.1 + tslib: 2.6.2 + dev: true + + /@nx/nx-darwin-arm64@16.5.1: + resolution: {integrity: sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-darwin-x64@16.5.1: + resolution: {integrity: sha512-j9HmL1l8k7EVJ3eOM5y8COF93gqrydpxCDoz23ZEtsY+JHY77VAiRQsmqBgEx9GGA2dXi9VEdS67B0+1vKariw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-freebsd-x64@16.5.1: + resolution: {integrity: sha512-CXSPT01aVS869tvCCF2tZ7LnCa8l41wJ3mTVtWBkjmRde68E5Up093hklRMyXb3kfiDYlfIKWGwrV4r0eH6x1A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-linux-arm-gnueabihf@16.5.1: + resolution: {integrity: sha512-BhrumqJSZCWFfLFUKl4CAUwR0Y0G2H5EfFVGKivVecEQbb+INAek1aa6c89evg2/OvetQYsJ+51QknskwqvLsA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-linux-arm64-gnu@16.5.1: + resolution: {integrity: sha512-x7MsSG0W+X43WVv7JhiSq2eKvH2suNKdlUHEG09Yt0vm3z0bhtym1UCMUg3IUAK7jy9hhLeDaFVFkC6zo+H/XQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-linux-arm64-musl@16.5.1: + resolution: {integrity: sha512-J+/v/mFjOm74I0PNtH5Ka+fDd+/dWbKhpcZ2R1/6b9agzZk+Ff/SrwJcSYFXXWKbPX+uQ4RcJoytT06Zs3s0ow==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-linux-x64-gnu@16.5.1: + resolution: {integrity: sha512-igooWJ5YxQ94Zft7IqgL+Lw0qHaY15Btw4gfK756g/YTYLZEt4tTvR1y6RnK/wdpE3sa68bFTLVBNCGTyiTiDQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-linux-x64-musl@16.5.1: + resolution: {integrity: sha512-zF/exnPqFYbrLAduGhTmZ7zNEyADid2bzNQiIjJkh8Y6NpDwrQIwVIyvIxqynsjMrIs51kBH+8TUjKjj2Jgf5A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-win32-arm64-msvc@16.5.1: + resolution: {integrity: sha512-qtqiLS9Y9TYyAbbpq58kRoOroko4ZXg5oWVqIWFHoxc5bGPweQSJCROEqd1AOl2ZDC6BxfuVHfhDDop1kK05WA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@nx/nx-win32-x64-msvc@16.5.1: + resolution: {integrity: sha512-kUJBLakK7iyA9WfsGGQBVennA4jwf5XIgm0lu35oMOphtZIluvzItMt0EYBmylEROpmpEIhHq0P6J9FA+WH0Rg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher@2.0.4: + resolution: {integrity: sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==} + engines: {node: '>= 10.0.0'} + requiresBuild: true + dependencies: + node-addon-api: 3.2.1 + node-gyp-build: 4.6.1 + dev: true + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@puppeteer/browsers@0.5.0(typescript@5.1.6): + resolution: {integrity: sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ==} + engines: {node: '>=14.1.0'} + hasBin: true + peerDependencies: + typescript: '>= 4.7.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + debug: 4.3.4 + extract-zip: 2.0.1 + https-proxy-agent: 5.0.1 + progress: 2.0.3 + proxy-from-env: 1.1.0 + tar-fs: 2.1.1 + typescript: 5.1.6 + unbzip2-stream: 1.4.3 + yargs: 17.7.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@schematics/angular@16.2.10: + resolution: {integrity: sha512-PXmoswvN7qknTsXDmEvhZ9UG+awwWnQ/1Jd/eqqQx08iAaAT81OsXj1bN7eSs6tEGBKGjPb6q2xzuiECAdymzg==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 16.2.10(chokidar@3.5.3) + '@angular-devkit/schematics': 16.2.10 + jsonc-parser: 3.2.0 + transitivePeerDependencies: + - chokidar + dev: true + + /@sigstore/bundle@1.1.0: + resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@sigstore/protobuf-specs': 0.2.1 + dev: true + + /@sigstore/protobuf-specs@0.2.1: + resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /@sigstore/sign@1.0.0: + resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@sigstore/bundle': 1.1.0 + '@sigstore/protobuf-specs': 0.2.1 + make-fetch-happen: 11.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@sigstore/tuf@1.0.3: + resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@sigstore/protobuf-specs': 0.2.1 + tuf-js: 1.1.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@socket.io/component-emitter@3.1.0: + resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} + dev: true + + /@tootallnate/once@1.1.2: + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + dev: true + + /@tootallnate/once@2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: true + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@tufjs/canonical-json@1.0.0: + resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /@tufjs/models@1.0.4: + resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@tufjs/canonical-json': 1.0.0 + minimatch: 9.0.3 + dev: true + + /@types/body-parser@1.19.5: + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + dependencies: + '@types/connect': 3.4.38 + '@types/node': 18.18.9 + dev: true + + /@types/bonjour@3.5.13: + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/connect-history-api-fallback@1.5.3: + resolution: {integrity: sha512-6mfQ6iNvhSKCZJoY6sIG3m0pKkdUcweVNOLuBBKvoWGzl2yRxOJcYOTRyLKt3nxXvBLJWa6QkW//tgbIwJehmA==} + dependencies: + '@types/express-serve-static-core': 4.17.41 + '@types/node': 18.18.9 + dev: true + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/cookie@0.4.1: + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + dev: true + + /@types/cors@2.8.16: + resolution: {integrity: sha512-Trx5or1Nyg1Fq138PCuWqoApzvoSLWzZ25ORBiHMbbUT42g578lH1GT4TwYDbiUOLFuDsCkfLneT2105fsFWGg==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/eslint-scope@3.7.7: + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + dependencies: + '@types/eslint': 8.44.7 + '@types/estree': 1.0.5 + dev: true + + /@types/eslint@8.44.7: + resolution: {integrity: sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/express-serve-static-core@4.17.41: + resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} + dependencies: + '@types/node': 18.18.9 + '@types/qs': 6.9.10 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + dev: true + + /@types/express@4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.17.41 + '@types/qs': 6.9.10 + '@types/serve-static': 1.15.5 + dev: true + + /@types/http-errors@2.0.4: + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + dev: true + + /@types/http-proxy@1.17.14: + resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/jasmine@4.3.6: + resolution: {integrity: sha512-3N0FpQTeiWjm+Oo1WUYWguUS7E6JLceiGTriFrG8k5PU7zRLJCzLcWURU3wjMbZGS//a2/LgjsnO3QxIlwxt9g==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/mime@1.3.5: + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + dev: true + + /@types/mime@3.0.4: + resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} + dev: true + + /@types/minimist@1.2.5: + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + dev: true + + /@types/node-forge@1.3.9: + resolution: {integrity: sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/node@18.18.9: + resolution: {integrity: sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/node@20.5.1: + resolution: {integrity: sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==} + dev: true + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/qs@6.9.10: + resolution: {integrity: sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==} + dev: true + + /@types/range-parser@1.2.7: + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: true + + /@types/retry@0.12.0: + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + dev: true + + /@types/semver@7.5.5: + resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==} + dev: true + + /@types/send@0.17.4: + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + dependencies: + '@types/mime': 1.3.5 + '@types/node': 18.18.9 + dev: true + + /@types/serve-index@1.9.4: + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + dependencies: + '@types/express': 4.17.21 + dev: true + + /@types/serve-static@1.15.5: + resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + dependencies: + '@types/http-errors': 2.0.4 + '@types/mime': 3.0.4 + '@types/node': 18.18.9 + dev: true + + /@types/sockjs@0.3.36: + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/ws@8.5.9: + resolution: {integrity: sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==} + dependencies: + '@types/node': 18.18.9 + dev: true + + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 18.18.9 + dev: true + optional: true + + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.53.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare-lite: 1.4.0 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.62.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.53.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: true + + /@typescript-eslint/type-utils@5.62.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.53.0 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.62.0(eslint@8.53.0)(typescript@5.1.6): + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.5 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + eslint: 8.53.0 + eslint-scope: 5.1.1 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@vitejs/plugin-basic-ssl@1.0.1(vite@4.4.7): + resolution: {integrity: sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==} + engines: {node: '>=14.6.0'} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 + dependencies: + vite: 4.4.7(@types/node@18.18.9)(less@4.1.3)(sass@1.64.1)(terser@5.19.2) + dev: true + + /@webassemblyjs/ast@1.11.6: + resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: true + + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: true + + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: true + + /@webassemblyjs/helper-buffer@1.11.6: + resolution: {integrity: sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==} + dev: true + + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: true + + /@webassemblyjs/helper-wasm-section@1.11.6: + resolution: {integrity: sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + dev: true + + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: true + + /@webassemblyjs/wasm-edit@1.11.6: + resolution: {integrity: sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-opt': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + '@webassemblyjs/wast-printer': 1.11.6 + dev: true + + /@webassemblyjs/wasm-gen@1.11.6: + resolution: {integrity: sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wasm-opt@1.11.6: + resolution: {integrity: sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + dev: true + + /@webassemblyjs/wasm-parser@1.11.6: + resolution: {integrity: sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wast-printer@1.11.6: + resolution: {integrity: sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@wessberg/ts-evaluator@0.0.27(typescript@5.1.6): + resolution: {integrity: sha512-7gOpVm3yYojUp/Yn7F4ZybJRxyqfMNf0LXK5KJiawbPfL0XTsJV+0mgrEDjOIR6Bi0OYk2Cyg4tjFu1r8MCZaA==} + engines: {node: '>=10.1.0'} + deprecated: this package has been renamed to ts-evaluator. Please install ts-evaluator instead + peerDependencies: + typescript: '>=3.2.x || >= 4.x' + dependencies: + chalk: 4.1.2 + jsdom: 16.7.0 + object-path: 0.11.8 + tslib: 2.6.2 + typescript: 5.1.6 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /@yarnpkg/lockfile@1.1.0: + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + dev: true + + /@yarnpkg/parsers@3.0.0-rc.46: + resolution: {integrity: sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==} + engines: {node: '>=14.15.0'} + dependencies: + js-yaml: 3.14.1 + tslib: 2.6.2 + dev: true + + /@zkochan/js-yaml@0.0.6: + resolution: {integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + + /abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + dev: true + + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: true + + /acorn-globals@6.0.0: + resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + dev: true + + /acorn-import-assertions@1.9.0(acorn@8.11.2): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-walk@7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn-walk@8.3.0: + resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.2.11 + dev: true + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + dependencies: + humanize-ms: 1.2.1 + dev: true + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: true + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv-keywords@5.1.0(ajv@8.12.0): + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + dependencies: + ajv: 8.12.0 + fast-deep-equal: 3.1.3 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: true + + /are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: true + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: true + + /array-flatten@2.1.2: + resolution: {integrity: sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==} + dev: true + + /array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + dev: true + + /array-includes@3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-string: 1.0.7 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.findlastindex@1.2.3: + resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + safer-buffer: 2.1.2 + dev: false + + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /autoprefixer@10.4.14(postcss@8.4.31): + resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.22.1 + caniuse-lite: 1.0.30001561 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.31 + postcss-value-parser: 4.2.0 + dev: true + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /axios@1.6.1: + resolution: {integrity: sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==} + dependencies: + follow-redirects: 1.15.3 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: true + + /axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: true + + /babel-loader@9.1.3(@babel/core@7.22.9)(webpack@5.88.2): + resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + dependencies: + '@babel/core': 7.22.9 + find-cache-dir: 4.0.0 + schema-utils: 4.2.0 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.22.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.22.9): + resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/compat-data': 7.23.3 + '@babel/core': 7.22.9 + '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.22.9) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.8.6(@babel/core@7.22.9): + resolution: {integrity: sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.22.9) + core-js-compat: 3.33.2 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.5.3(@babel/core@7.22.9): + resolution: {integrity: sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /balanced-match@2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + dev: true + + /batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + dev: true + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + + /bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: false + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /bonjour-service@1.1.1: + resolution: {integrity: sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==} + dependencies: + array-flatten: 2.1.2 + dns-equal: 1.0.0 + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + dev: true + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: false + + /browser-process-hrtime@1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + dev: true + + /browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.4 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + dev: false + + /browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + dependencies: + cipher-base: 1.0.4 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-rsa@4.1.0: + resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==} + dependencies: + bn.js: 5.2.1 + randombytes: 2.1.0 + dev: false + + /browserify-sign@4.2.2: + resolution: {integrity: sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==} + engines: {node: '>= 4'} + dependencies: + bn.js: 5.2.1 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.5.4 + inherits: 2.0.4 + parse-asn1: 5.1.6 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + dev: false + + /browserslist@4.22.1: + resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001561 + electron-to-chromium: 1.4.579 + node-releases: 2.0.13 + update-browserslist-db: 1.0.13(browserslist@4.22.1) + dev: true + + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + dev: false + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.5.4 + dev: true + + /bytes@3.0.0: + resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} + engines: {node: '>= 0.8'} + dev: true + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: true + + /cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.2.0 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + dev: true + + /cacache@17.1.4: + resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/fs': 3.1.0 + fs-minipass: 3.0.3 + glob: 10.3.10 + lru-cache: 7.18.3 + minipass: 7.0.4 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 4.0.0 + ssri: 10.0.5 + tar: 6.2.0 + unique-filename: 3.0.0 + dev: true + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + dev: true + + /camelcase-keys@7.0.2: + resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} + engines: {node: '>=12'} + dependencies: + camelcase: 6.3.0 + map-obj: 4.3.0 + quick-lru: 5.1.1 + type-fest: 1.4.0 + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite@1.0.30001561: + resolution: {integrity: sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: true + + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /chromium-bidi@0.4.7(devtools-protocol@0.0.1107588): + resolution: {integrity: sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==} + peerDependencies: + devtools-protocol: '*' + dependencies: + devtools-protocol: 0.0.1107588 + mitt: 3.0.0 + dev: true + + /cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-spinners@2.6.1: + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} + dev: true + + /cli-spinners@2.9.1: + resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} + engines: {node: '>=6'} + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + dev: true + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: true + + /colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + dev: true + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + dev: true + + /compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + dev: true + + /compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /compression@1.7.4: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + dev: true + + /connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: true + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: true + + /conventional-changelog-angular@6.0.0: + resolution: {integrity: sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==} + engines: {node: '>=14'} + dependencies: + compare-func: 2.0.0 + dev: true + + /conventional-changelog-conventionalcommits@6.1.0: + resolution: {integrity: sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==} + engines: {node: '>=14'} + dependencies: + compare-func: 2.0.0 + dev: true + + /conventional-commits-parser@4.0.0: + resolution: {integrity: sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==} + engines: {node: '>=14'} + hasBin: true + dependencies: + JSONStream: 1.3.5 + is-text-path: 1.0.1 + meow: 8.1.2 + split2: 3.2.2 + dev: true + + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: true + + /cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + dev: true + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: true + + /copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + dependencies: + is-what: 3.14.1 + dev: true + + /copy-webpack-plugin@11.0.0(webpack@5.88.2): + resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.1.0 + dependencies: + fast-glob: 3.3.1 + glob-parent: 6.0.2 + globby: 13.2.2 + normalize-path: 3.0.0 + schema-utils: 4.2.0 + serialize-javascript: 6.0.1 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /core-js-compat@3.33.2: + resolution: {integrity: sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==} + dependencies: + browserslist: 4.22.1 + dev: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: true + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + + /cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6)(ts-node@10.9.1)(typescript@5.2.2): + resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} + engines: {node: '>=v14.21.3'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=7' + ts-node: '>=10' + typescript: '>=4' + dependencies: + '@types/node': 20.5.1 + cosmiconfig: 8.3.6(typescript@5.1.6) + ts-node: 10.9.1(@types/node@18.18.9)(typescript@5.1.6) + typescript: 5.2.2 + dev: true + + /cosmiconfig@8.1.3: + resolution: {integrity: sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==} + engines: {node: '>=14'} + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + dev: true + + /cosmiconfig@8.3.6(typescript@5.1.6): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.1.6 + dev: true + + /create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + dependencies: + bn.js: 4.12.0 + elliptic: 6.5.4 + dev: false + + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: false + + /create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + dependencies: + cipher-base: 1.0.4 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: false + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /critters@0.0.20: + resolution: {integrity: sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==} + dependencies: + chalk: 4.1.2 + css-select: 5.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + htmlparser2: 8.0.2 + postcss: 8.4.31 + pretty-bytes: 5.6.0 + dev: true + + /cropperjs@1.6.1: + resolution: {integrity: sha512-F4wsi+XkDHCOMrHMYjrTEE4QBOrsHHN5/2VsVAaRq8P7E5z7xQpT75S+f/9WikmBEailas3+yo+6zPIomW+NOA==} + dev: false + + /cross-fetch@3.1.5: + resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} + dependencies: + node-fetch: 2.6.7 + transitivePeerDependencies: + - encoding + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crypto-browserify@3.12.0: + resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.2 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + inherits: 2.0.4 + pbkdf2: 3.1.2 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + dev: false + + /css-functions-list@3.2.1: + resolution: {integrity: sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==} + engines: {node: '>=12 || >=16'} + dev: true + + /css-loader@6.8.1(webpack@5.88.2): + resolution: {integrity: sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.31) + postcss: 8.4.31 + postcss-modules-extract-imports: 3.0.0(postcss@8.4.31) + postcss-modules-local-by-default: 4.0.3(postcss@8.4.31) + postcss-modules-scope: 3.0.0(postcss@8.4.31) + postcss-modules-values: 4.0.0(postcss@8.4.31) + postcss-value-parser: 4.2.0 + semver: 7.5.4 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + dev: true + + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: true + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + dev: true + + /cssom@0.4.4: + resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} + dev: true + + /cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + dependencies: + cssom: 0.3.8 + dev: true + + /custom-event@1.0.1: + resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} + dev: true + + /dargs@7.0.0: + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} + dev: true + + /data-urls@2.0.0: + resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} + engines: {node: '>=10'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + dev: true + + /date-format@4.0.14: + resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} + engines: {node: '>=4.0'} + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + requiresBuild: true + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decamelize@5.0.1: + resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} + engines: {node: '>=10'} + dev: true + + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + dependencies: + execa: 5.1.1 + dev: true + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: true + + /depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: true + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: true + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: true + + /detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + dev: true + + /devtools-protocol@0.0.1107588: + resolution: {integrity: sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==} + dev: true + + /di@0.0.1: + resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==} + dev: true + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dependencies: + bn.js: 4.12.0 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + dev: false + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dns-equal@1.0.0: + resolution: {integrity: sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==} + dev: true + + /dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + dependencies: + '@leichtgewicht/ip-codec': 2.0.4 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-serialize@2.2.1: + resolution: {integrity: sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==} + dependencies: + custom-event: 1.0.1 + ent: 2.2.0 + extend: 3.0.2 + void-elements: 2.0.1 + dev: true + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dev: true + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: true + + /domexception@2.0.1: + resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} + engines: {node: '>=8'} + dependencies: + webidl-conversions: 5.0.0 + dev: true + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: true + + /dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /dotenv@10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + dev: true + + /duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: true + + /ejs@3.1.9: + resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.8.7 + dev: true + + /electron-to-chromium@1.4.579: + resolution: {integrity: sha512-bJKvA+awBIzYR0xRced7PrQuRIwGQPpo6ZLP62GAShahU9fWpsNN2IP6BSP1BLDDSbxvBVRGAMWlvVVq3npmLA==} + dev: true + + /elliptic@6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: true + + /encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + requiresBuild: true + dependencies: + iconv-lite: 0.6.3 + dev: true + optional: true + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + + /engine.io-parser@5.2.1: + resolution: {integrity: sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==} + engines: {node: '>=10.0.0'} + dev: true + + /engine.io@6.5.4: + resolution: {integrity: sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==} + engines: {node: '>=10.2.0'} + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.16 + '@types/node': 18.18.9 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.4.2 + cors: 2.8.5 + debug: 4.3.4 + engine.io-parser: 5.2.1 + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + dev: true + + /ent@2.2.0: + resolution: {integrity: sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==} + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + + /err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + dev: true + + /errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + requiresBuild: true + dependencies: + prr: 1.0.1 + dev: true + optional: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: true + + /es-module-lexer@1.3.1: + resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==} + dev: true + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild-wasm@0.18.17: + resolution: {integrity: sha512-9OHGcuRzy+I8ziF9FzjfKLWAPbvi0e/metACVg9k6bK+SI4FFxeV6PcZsz8RIVaMD4YNehw+qj6UMR3+qj/EuQ==} + engines: {node: '>=12'} + hasBin: true + dev: true + + /esbuild@0.18.17: + resolution: {integrity: sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.17 + '@esbuild/android-arm64': 0.18.17 + '@esbuild/android-x64': 0.18.17 + '@esbuild/darwin-arm64': 0.18.17 + '@esbuild/darwin-x64': 0.18.17 + '@esbuild/freebsd-arm64': 0.18.17 + '@esbuild/freebsd-x64': 0.18.17 + '@esbuild/linux-arm': 0.18.17 + '@esbuild/linux-arm64': 0.18.17 + '@esbuild/linux-ia32': 0.18.17 + '@esbuild/linux-loong64': 0.18.17 + '@esbuild/linux-mips64el': 0.18.17 + '@esbuild/linux-ppc64': 0.18.17 + '@esbuild/linux-riscv64': 0.18.17 + '@esbuild/linux-s390x': 0.18.17 + '@esbuild/linux-x64': 0.18.17 + '@esbuild/netbsd-x64': 0.18.17 + '@esbuild/openbsd-x64': 0.18.17 + '@esbuild/sunos-x64': 0.18.17 + '@esbuild/win32-arm64': 0.18.17 + '@esbuild/win32-ia32': 0.18.17 + '@esbuild/win32-x64': 0.18.17 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + + /eslint-config-prettier@8.10.0(eslint@8.53.0): + resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.53.0 + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0)(eslint-plugin-import@2.29.0)(eslint@8.53.0): + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.15.0 + eslint: 8.53.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) + fast-glob: 3.3.2 + get-tsconfig: 4.7.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + debug: 3.2.7 + eslint: 8.53.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0)(eslint-plugin-import@2.29.0)(eslint@8.53.0) + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-html@7.1.0: + resolution: {integrity: sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==} + dependencies: + htmlparser2: 8.0.2 + dev: true + + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0): + resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.62.0(eslint@8.53.0)(typescript@5.1.6) + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.53.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.53.0) + hasown: 2.0.0 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0)(eslint@8.53.0)(prettier@2.8.8): + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.53.0 + eslint-config-prettier: 8.10.0(eslint@8.53.0) + prettier: 2.8.8 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.53.0: + resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.3 + '@eslint/js': 8.53.0 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.23.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.2 + acorn-jsx: 5.3.2(acorn@8.11.2) + eslint-visitor-keys: 3.4.3 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: true + + /eventemitter-asyncresource@1.0.0: + resolution: {integrity: sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==} + dev: true + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: true + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + dev: false + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + dev: true + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.2.7: + resolution: {integrity: sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==} + engines: {node: '>=8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + dependencies: + websocket-driver: 0.7.4 + dev: true + + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.1.1 + dev: true + + /file-entry-cache@7.0.1: + resolution: {integrity: sha512-uLfFktPmRetVCbHe5UPuekWrQ6hENufnA46qEGbfACkK5drjTTdQYUragRgMjHldcbYG+nslUerqMPjbBSHXjQ==} + engines: {node: '>=12.0.0'} + dependencies: + flat-cache: 3.1.1 + dev: true + + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /find-cache-dir@4.0.0: + resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} + engines: {node: '>=14.16'} + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + dev: true + + /flat-cache@3.1.1: + resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} + engines: {node: '>=12.0.0'} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + dev: true + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /follow-redirects@1.15.3: + resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /form-data@3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: true + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: true + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: true + + /fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: true + + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minipass: 7.0.4 + dev: true + + /fs-monkey@1.0.5: + resolution: {integrity: sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: true + + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /git-raw-commits@2.0.11: + resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + dargs: 7.0.0 + lodash: 4.17.21 + meow: 8.1.2 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.1 + dev: true + + /glob@7.1.4: + resolution: {integrity: sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + + /global-dirs@0.1.1: + resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} + engines: {node: '>=4'} + dependencies: + ini: 1.3.8 + dev: true + + /global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + dependencies: + global-prefix: 3.0.0 + dev: true + + /global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /globjoin@0.1.4: + resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /guess-parser@0.4.22(typescript@5.1.6): + resolution: {integrity: sha512-KcUWZ5ACGaBM69SbqwVIuWGoSAgD+9iJnchR9j/IarVI1jHVeXv+bUXBIMeqVMSKt3zrn0Dgf9UpcOEpPBLbSg==} + peerDependencies: + typescript: '>=3.7.5' + dependencies: + '@wessberg/ts-evaluator': 0.0.27(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + dev: true + + /hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: true + + /hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + dev: false + + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /hdr-histogram-js@2.0.3: + resolution: {integrity: sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==} + dependencies: + '@assemblyscript/loader': 0.10.1 + base64-js: 1.5.1 + pako: 1.0.11 + dev: true + + /hdr-histogram-percentiles-obj@3.0.0: + resolution: {integrity: sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==} + dev: true + + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /hosted-git-info@6.1.1: + resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + lru-cache: 7.18.3 + dev: true + + /hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + dev: true + + /html-encoding-sniffer@2.0.1: + resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} + engines: {node: '>=10'} + dependencies: + whatwg-encoding: 1.0.5 + dev: true + + /html-entities@2.4.0: + resolution: {integrity: sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==} + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + dev: true + + /htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + dev: true + + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + + /http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + dev: true + + /http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: true + + /http-parser-js@0.5.8: + resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} + dev: true + + /http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /http-proxy-middleware@2.0.6(@types/express@4.17.21): + resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + dependencies: + '@types/express': 4.17.21 + '@types/http-proxy': 1.17.14 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.5 + transitivePeerDependencies: + - debug + dev: true + + /http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.3 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + dev: true + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.3 + dev: true + + /husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /icss-utils@5.1.0(postcss@8.4.31): + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.31 + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore-walk@6.0.3: + resolution: {integrity: sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minimatch: 9.0.3 + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /immutable@4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + + /infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /inquirer@8.2.4: + resolution: {integrity: sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /install@0.13.0: + resolution: {integrity: sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==} + engines: {node: '>= 0.10'} + dev: false + + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: true + + /ip@2.0.0: + resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + dev: true + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: true + + /ipaddr.js@2.1.0: + resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} + engines: {node: '>= 10'} + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + + /is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + dev: true + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: true + + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-text-path@1.0.1: + resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} + engines: {node: '>=0.10.0'} + dependencies: + text-extensions: 1.9.0 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: true + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + dev: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isbinaryfile@4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.23.3 + '@babel/parser': 7.23.3 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jake@10.8.7: + resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.5 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + + /jasmine-core@4.5.0: + resolution: {integrity: sha512-9PMzyvhtocxb3aXJVOPqBDswdgyAeSB81QnLop4npOpbqnheaTEwPc9ZloQeVswugPManznQBjD8kWDTjlnHuw==} + dev: true + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 18.18.9 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsdom@16.7.0: + resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} + engines: {node: '>=10'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.6 + acorn: 8.11.2 + acorn-globals: 6.0.0 + cssom: 0.4.4 + cssstyle: 2.3.0 + data-urls: 2.0.0 + decimal.js: 10.4.3 + domexception: 2.0.1 + escodegen: 2.1.0 + form-data: 3.0.1 + html-encoding-sniffer: 2.0.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 + parse5: 6.0.1 + saxes: 5.0.1 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-hr-time: 1.0.2 + w3c-xmlserializer: 2.0.0 + webidl-conversions: 6.1.0 + whatwg-encoding: 1.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + ws: 7.5.9 + xml-name-validator: 3.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-parse-even-better-errors@3.0.0: + resolution: {integrity: sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true + + /karma-chrome-launcher@3.1.1: + resolution: {integrity: sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==} + dependencies: + which: 1.3.1 + dev: true + + /karma-coverage@2.2.1: + resolution: {integrity: sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==} + engines: {node: '>=10.0.0'} + dependencies: + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /karma-jasmine-html-reporter@2.0.0(jasmine-core@4.5.0)(karma-jasmine@5.1.0)(karma@6.4.2): + resolution: {integrity: sha512-SB8HNNiazAHXM1vGEzf8/tSyEhkfxuDdhYdPBX2Mwgzt0OuF2gicApQ+uvXLID/gXyJQgvrM9+1/2SxZFUUDIA==} + peerDependencies: + jasmine-core: ^4.0.0 + karma: ^6.0.0 + karma-jasmine: ^5.0.0 + dependencies: + jasmine-core: 4.5.0 + karma: 6.4.2 + karma-jasmine: 5.1.0(karma@6.4.2) + dev: true + + /karma-jasmine@5.1.0(karma@6.4.2): + resolution: {integrity: sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==} + engines: {node: '>=12'} + peerDependencies: + karma: ^6.0.0 + dependencies: + jasmine-core: 4.5.0 + karma: 6.4.2 + dev: true + + /karma-source-map-support@1.4.0: + resolution: {integrity: sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==} + dependencies: + source-map-support: 0.5.21 + dev: true + + /karma@6.4.2: + resolution: {integrity: sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==} + engines: {node: '>= 10'} + hasBin: true + dependencies: + '@colors/colors': 1.5.0 + body-parser: 1.20.2 + braces: 3.0.2 + chokidar: 3.5.3 + connect: 3.7.0 + di: 0.0.1 + dom-serialize: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + http-proxy: 1.18.1 + isbinaryfile: 4.0.10 + lodash: 4.17.21 + log4js: 6.9.1 + mime: 2.6.0 + minimatch: 3.1.2 + mkdirp: 0.5.6 + qjobs: 1.2.0 + range-parser: 1.2.1 + rimraf: 3.0.2 + socket.io: 4.7.2 + source-map: 0.6.1 + tmp: 0.2.1 + ua-parser-js: 0.7.37 + yargs: 16.2.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + dev: true + + /known-css-properties@0.29.0: + resolution: {integrity: sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==} + dev: true + + /launch-editor@2.6.1: + resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} + dependencies: + picocolors: 1.0.0 + shell-quote: 1.8.1 + dev: true + + /less-loader@11.1.0(less@4.1.3)(webpack@5.88.2): + resolution: {integrity: sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==} + engines: {node: '>= 14.15.0'} + peerDependencies: + less: ^3.5.0 || ^4.0.0 + webpack: ^5.0.0 + dependencies: + klona: 2.0.6 + less: 4.1.3 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /less@4.1.3: + resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.6.2 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /license-webpack-plugin@4.0.2(webpack@5.88.2): + resolution: {integrity: sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==} + peerDependencies: + webpack: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-sources: + optional: true + dependencies: + webpack: 5.88.2(esbuild@0.18.17) + webpack-sources: 3.2.3 + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /lines-and-columns@2.0.4: + resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: true + + /loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + dev: true + + /loader-utils@3.2.1: + resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==} + engines: {node: '>= 12.13.0'} + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: true + + /lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + dev: true + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: true + + /lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + dev: true + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + dev: true + + /lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /log4js@6.9.1: + resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} + engines: {node: '>=8.0'} + dependencies: + date-format: 4.0.14 + debug: 4.3.4 + flatted: 3.2.9 + rfdc: 1.3.0 + streamroller: 3.1.5 + transitivePeerDependencies: + - supports-color + dev: true + + /lru-cache@10.0.1: + resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: true + + /magic-string@0.30.1: + resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + pify: 4.0.1 + semver: 5.7.2 + dev: true + optional: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + agentkeepalive: 4.5.0 + cacache: 16.1.3 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /make-fetch-happen@11.1.1: + resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + agentkeepalive: 4.5.0 + cacache: 17.1.4 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 5.0.0 + minipass-fetch: 3.0.4 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 10.0.5 + transitivePeerDependencies: + - supports-color + dev: true + + /map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /mathml-tag-names@2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + dev: true + + /md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: true + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: true + + /memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + dependencies: + fs-monkey: 1.0.5 + dev: true + + /meow@10.1.5: + resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 7.0.2 + decamelize: 5.0.1 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 8.0.0 + redent: 4.0.0 + trim-newlines: 4.1.1 + type-fest: 1.4.0 + yargs-parser: 20.2.9 + dev: true + + /meow@8.1.2: + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + dev: true + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /mini-css-extract-plugin@2.7.6(webpack@5.88.2): + resolution: {integrity: sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + schema-utils: 4.2.0 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: false + + /minimatch@3.0.5: + resolution: {integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: true + + /minipass-fetch@3.0.4: + resolution: {integrity: sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minipass: 7.0.4 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: true + + /minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass-json-stream@1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + dependencies: + jsonparse: 1.3.1 + minipass: 3.3.6 + dev: true + + /minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true + + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: true + + /mitt@3.0.0: + resolution: {integrity: sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==} + dev: true + + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: true + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mrmime@1.0.1: + resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} + engines: {node: '>=10'} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + dev: true + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /needle@3.2.0: + resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + requiresBuild: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.6.3 + sax: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: true + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /ng-hcaptcha@2.2.0(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/forms@16.2.12): + resolution: {integrity: sha512-opaVb96eFk1N0RjW5X0HniGN9+2bN9CmuKwfFl2UxVHhkTx+H37kE/PY6af0ikve3QQZAJYetc9hYfQ6l9ZU7Q==} + peerDependencies: + '@angular/common': ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + '@angular/core': ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + '@angular/forms': ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@angular/common': 16.2.12(@angular/core@16.2.12)(rxjs@7.8.1) + '@angular/core': 16.2.12(rxjs@7.8.1)(zone.js@0.13.3) + '@angular/forms': 16.2.12(@angular/common@16.2.12)(@angular/core@16.2.12)(@angular/platform-browser@16.2.12)(rxjs@7.8.1) + tslib: 2.6.2 + dev: false + + /nice-napi@1.0.2: + resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} + os: ['!win32'] + requiresBuild: true + dependencies: + node-addon-api: 3.2.1 + node-gyp-build: 4.6.1 + dev: true + optional: true + + /node-addon-api@3.2.1: + resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + requiresBuild: true + dev: true + + /node-fetch@2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: true + + /node-gyp-build@4.6.1: + resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==} + hasBin: true + requiresBuild: true + dev: true + + /node-gyp@9.4.1: + resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} + engines: {node: ^12.13 || ^14.13 || >=16} + hasBin: true + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + make-fetch-happen: 10.2.1 + nopt: 6.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.5.4 + tar: 6.2.0 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: true + + /nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.13.1 + semver: 7.5.4 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-package-data@5.0.0: + resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + hosted-git-info: 6.1.1 + is-core-module: 2.13.1 + semver: 7.5.4 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-bundled@3.0.0: + resolution: {integrity: sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + npm-normalize-package-bin: 3.0.1 + dev: true + + /npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + semver: 7.5.4 + dev: true + + /npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /npm-package-arg@10.1.0: + resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + hosted-git-info: 6.1.1 + proc-log: 3.0.0 + semver: 7.5.4 + validate-npm-package-name: 5.0.0 + dev: true + + /npm-packlist@7.0.4: + resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + ignore-walk: 6.0.3 + dev: true + + /npm-pick-manifest@8.0.1: + resolution: {integrity: sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + npm-install-checks: 6.3.0 + npm-normalize-package-bin: 3.0.1 + npm-package-arg: 10.1.0 + semver: 7.5.4 + dev: true + + /npm-registry-fetch@14.0.5: + resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + make-fetch-happen: 11.1.1 + minipass: 5.0.0 + minipass-fetch: 3.0.4 + minipass-json-stream: 1.0.1 + minizlib: 2.1.2 + npm-package-arg: 10.1.0 + proc-log: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + dev: true + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + dev: true + + /nx@16.5.1: + resolution: {integrity: sha512-I3hJRE4hG7JWAtncWwDEO3GVeGPpN0TtM8xH5ArZXyDuVeTth/i3TtJzdDzqXO1HHtIoAQN0xeq4n9cLuMil5g==} + hasBin: true + requiresBuild: true + peerDependencies: + '@swc-node/register': ^1.4.2 + '@swc/core': ^1.2.173 + peerDependenciesMeta: + '@swc-node/register': + optional: true + '@swc/core': + optional: true + dependencies: + '@nrwl/tao': 16.5.1 + '@parcel/watcher': 2.0.4 + '@yarnpkg/lockfile': 1.1.0 + '@yarnpkg/parsers': 3.0.0-rc.46 + '@zkochan/js-yaml': 0.0.6 + axios: 1.6.1 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + cliui: 7.0.4 + dotenv: 10.0.0 + enquirer: 2.3.6 + fast-glob: 3.2.7 + figures: 3.2.0 + flat: 5.0.2 + fs-extra: 11.1.1 + glob: 7.1.4 + ignore: 5.2.4 + js-yaml: 4.1.0 + jsonc-parser: 3.2.0 + lines-and-columns: 2.0.4 + minimatch: 3.0.5 + npm-run-path: 4.0.1 + open: 8.4.2 + semver: 7.5.3 + string-width: 4.2.3 + strong-log-transformer: 2.1.0 + tar-stream: 2.2.0 + tmp: 0.2.1 + tsconfig-paths: 4.2.0 + tslib: 2.6.2 + v8-compile-cache: 2.3.0 + yargs: 17.7.2 + yargs-parser: 21.1.1 + optionalDependencies: + '@nx/nx-darwin-arm64': 16.5.1 + '@nx/nx-darwin-x64': 16.5.1 + '@nx/nx-freebsd-x64': 16.5.1 + '@nx/nx-linux-arm-gnueabihf': 16.5.1 + '@nx/nx-linux-arm64-gnu': 16.5.1 + '@nx/nx-linux-arm64-musl': 16.5.1 + '@nx/nx-linux-x64-gnu': 16.5.1 + '@nx/nx-linux-x64-musl': 16.5.1 + '@nx/nx-win32-arm64-msvc': 16.5.1 + '@nx/nx-win32-x64-msvc': 16.5.1 + transitivePeerDependencies: + - debug + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object-path@0.11.8: + resolution: {integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==} + engines: {node: '>= 10.12.0'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.fromentries@2.0.7: + resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /object.groupby@1.0.1: + resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + dev: true + + /object.values@1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + dev: true + + /on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.1 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /pacote@15.2.0: + resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + '@npmcli/git': 4.1.0 + '@npmcli/installed-package-contents': 2.0.2 + '@npmcli/promise-spawn': 6.0.2 + '@npmcli/run-script': 6.0.2 + cacache: 17.1.4 + fs-minipass: 3.0.3 + minipass: 5.0.0 + npm-package-arg: 10.1.0 + npm-packlist: 7.0.4 + npm-pick-manifest: 8.0.1 + npm-registry-fetch: 14.0.5 + proc-log: 3.0.0 + promise-retry: 2.0.1 + read-package-json: 6.0.4 + read-package-json-fast: 3.0.2 + sigstore: 1.9.0 + ssri: 10.0.5 + tar: 6.2.0 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-asn1@5.1.6: + resolution: {integrity: sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==} + dependencies: + asn1.js: 5.4.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + pbkdf2: 3.1.2 + safe-buffer: 5.2.1 + dev: false + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + dev: true + + /parse5-html-rewriting-stream@7.0.0: + resolution: {integrity: sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==} + dependencies: + entities: 4.5.0 + parse5: 7.1.2 + parse5-sax-parser: 7.0.0 + dev: true + + /parse5-sax-parser@7.0.0: + resolution: {integrity: sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==} + dependencies: + parse5: 7.1.2 + dev: true + + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: true + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.0.1 + minipass: 7.0.4 + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: false + + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + requiresBuild: true + dev: true + optional: true + + /piscina@4.0.0: + resolution: {integrity: sha512-641nAmJS4k4iqpNUqfggqUBUMmlw0ZoM5VZKdQkV2e970Inn3Tk9kroCc1wpsYLD07vCwpys5iY0d3xI/9WkTg==} + dependencies: + eventemitter-asyncresource: 1.0.0 + hdr-histogram-js: 2.0.3 + hdr-histogram-percentiles-obj: 3.0.0 + optionalDependencies: + nice-napi: 1.0.2 + dev: true + + /pkg-dir@7.0.0: + resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} + engines: {node: '>=14.16'} + dependencies: + find-up: 6.3.0 + dev: true + + /postcss-loader@7.3.3(postcss@8.4.31)(typescript@5.1.6)(webpack@5.88.2): + resolution: {integrity: sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + dependencies: + cosmiconfig: 8.3.6(typescript@5.1.6) + jiti: 1.21.0 + postcss: 8.4.31 + semver: 7.5.4 + webpack: 5.88.2(esbuild@0.18.17) + transitivePeerDependencies: + - typescript + dev: true + + /postcss-media-query-parser@0.2.3: + resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} + dev: true + + /postcss-modules-extract-imports@3.0.0(postcss@8.4.31): + resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.31 + dev: true + + /postcss-modules-local-by-default@4.0.3(postcss@8.4.31): + resolution: {integrity: sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.31) + postcss: 8.4.31 + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-modules-scope@3.0.0(postcss@8.4.31): + resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.31 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-modules-values@4.0.0(postcss@8.4.31): + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.31) + postcss: 8.4.31 + dev: true + + /postcss-resolve-nested-selector@0.1.1: + resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} + dev: true + + /postcss-safe-parser@6.0.0(postcss@8.4.31): + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + dependencies: + postcss: 8.4.31 + dev: true + + /postcss-scss@4.0.9(postcss@8.4.31): + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + dependencies: + postcss: 8.4.31 + dev: true + + /postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + dev: true + + /proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: true + + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true + + /promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dev: true + + /promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + dev: true + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: true + + /prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + requiresBuild: true + dev: true + optional: true + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + + /public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + dependencies: + bn.js: 4.12.0 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + parse-asn1: 5.1.6 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /puppeteer-core@19.11.1(typescript@5.1.6): + resolution: {integrity: sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA==} + engines: {node: '>=14.14.0'} + peerDependencies: + typescript: '>= 4.7.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@puppeteer/browsers': 0.5.0(typescript@5.1.6) + chromium-bidi: 0.4.7(devtools-protocol@0.0.1107588) + cross-fetch: 3.1.5 + debug: 4.3.4 + devtools-protocol: 0.0.1107588 + extract-zip: 2.0.1 + https-proxy-agent: 5.0.1 + proxy-from-env: 1.1.0 + tar-fs: 2.1.1 + typescript: 5.1.6 + unbzip2-stream: 1.4.3 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: true + + /puppeteer@19.11.1(typescript@5.1.6): + resolution: {integrity: sha512-39olGaX2djYUdhaQQHDZ0T0GwEp+5f9UB9HmEP0qHfdQHIq0xGQZuAZ5TLnJIc/88SrPLpEflPC+xUqOTv3c5g==} + requiresBuild: true + dependencies: + '@puppeteer/browsers': 0.5.0(typescript@5.1.6) + cosmiconfig: 8.1.3 + https-proxy-agent: 5.0.1 + progress: 2.0.3 + proxy-from-env: 1.1.0 + puppeteer-core: 19.11.1(typescript@5.1.6) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + dev: true + + /qjobs@1.2.0: + resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==} + engines: {node: '>=0.9'} + dev: true + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + + /randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: true + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + json-parse-even-better-errors: 3.0.0 + npm-normalize-package-bin: 3.0.1 + dev: true + + /read-package-json@6.0.4: + resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + glob: 10.3.10 + json-parse-even-better-errors: 3.0.0 + normalize-package-data: 5.0.0 + npm-normalize-package-bin: 3.0.1 + dev: true + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg-up@8.0.0: + resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==} + engines: {node: '>=12'} + dependencies: + find-up: 5.0.0 + read-pkg: 6.0.0 + type-fest: 1.4.0 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /read-pkg@6.0.0: + resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} + engines: {node: '>=12'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 3.0.3 + parse-json: 5.2.0 + type-fest: 1.4.0 + dev: true + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + + /redent@4.0.0: + resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} + engines: {node: '>=12'} + dependencies: + indent-string: 5.0.0 + strip-indent: 4.0.0 + dev: true + + /reflect-metadata@0.1.13: + resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} + dev: true + + /regenerate-unicode-properties@10.1.1: + resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: true + + /regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + dependencies: + '@babel/runtime': 7.22.6 + dev: true + + /regex-parser@2.2.11: + resolution: {integrity: sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==} + dev: true + + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.1 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + dev: true + + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-global@1.0.0: + resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==} + engines: {node: '>=8'} + dependencies: + global-dirs: 0.1.1 + dev: true + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve-url-loader@5.0.0: + resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==} + engines: {node: '>=12'} + dependencies: + adjust-sourcemap-loader: 4.0.0 + convert-source-map: 1.9.0 + loader-utils: 2.0.4 + postcss: 8.4.31 + source-map: 0.6.1 + dev: true + + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + dev: true + + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: false + + /rollup@3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.2 + + /safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + /sass-loader@13.3.2(sass@1.64.1)(webpack@5.88.2): + resolution: {integrity: sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==} + engines: {node: '>= 14.15.0'} + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + dependencies: + neo-async: 2.6.2 + sass: 1.64.1 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /sass@1.64.1: + resolution: {integrity: sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.4 + source-map-js: 1.0.2 + dev: true + + /sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + requiresBuild: true + dev: true + optional: true + + /saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + dependencies: + xmlchars: 2.2.0 + dev: true + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: true + + /schema-utils@4.2.0: + resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} + engines: {node: '>= 12.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + ajv-keywords: 5.1.0(ajv@8.12.0) + dev: true + + /select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + dev: true + + /selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + dependencies: + '@types/node-forge': 1.3.9 + node-forge: 1.3.1 + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.5.3: + resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + + /setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + dev: true + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: true + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + dependencies: + kind-of: 6.0.3 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /sigstore@1.9.0: + resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + '@sigstore/bundle': 1.1.0 + '@sigstore/protobuf-specs': 0.2.1 + '@sigstore/sign': 1.0.0 + '@sigstore/tuf': 1.0.3 + make-fetch-happen: 11.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: true + + /socket.io-adapter@2.5.2: + resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==} + dependencies: + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /socket.io@4.7.2: + resolution: {integrity: sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==} + engines: {node: '>=10.2.0'} + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.4 + engine.io: 6.5.4 + socket.io-adapter: 2.5.2 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + dev: true + + /socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: true + + /socks@2.7.1: + resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 2.0.0 + smart-buffer: 4.2.0 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map-loader@4.0.1(webpack@5.88.2): + resolution: {integrity: sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.72.1 + dependencies: + abab: 2.0.6 + iconv-lite: 0.6.3 + source-map-js: 1.0.2 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-license-ids@3.0.16: + resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + dev: true + + /spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + dependencies: + debug: 4.3.4 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + dev: true + + /spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + dependencies: + debug: 4.3.4 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /split2@3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + dependencies: + readable-stream: 3.6.2 + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /ssri@10.0.5: + resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minipass: 7.0.4 + dev: true + + /ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minipass: 3.3.6 + dev: true + + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: true + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: true + + /stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /streamroller@3.1.5: + resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} + engines: {node: '>=8.0'} + dependencies: + date-format: 4.0.14 + debug: 4.3.4 + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-indent@4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strong-log-transformer@2.1.0: + resolution: {integrity: sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==} + engines: {node: '>=4'} + hasBin: true + dependencies: + duplexer: 0.1.2 + minimist: 1.2.8 + through: 2.3.8 + dev: true + + /style-search@0.1.0: + resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} + dev: true + + /stylelint-config-recommended-scss@10.0.0(postcss@8.4.31)(stylelint@15.11.0): + resolution: {integrity: sha512-+YvPgUHi0W5mCJCKdupBCIsWPYNbWuJcRmFtSYujwNg+41ljFknhO9bpY6C+oahv659zW7W1AT7i6DQvJYYr1A==} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^15.3.0 + peerDependenciesMeta: + postcss: + optional: true + dependencies: + postcss: 8.4.31 + postcss-scss: 4.0.9(postcss@8.4.31) + stylelint: 15.11.0(typescript@5.1.6) + stylelint-config-recommended: 11.0.0(stylelint@15.11.0) + stylelint-scss: 4.7.0(stylelint@15.11.0) + dev: true + + /stylelint-config-recommended@11.0.0(stylelint@15.11.0): + resolution: {integrity: sha512-SoGIHNI748OCZn6BxFYT83ytWoYETCINVHV3LKScVAWQQauWdvmdDqJC5YXWjpBbxg2E761Tg5aUGKLFOVhEkA==} + peerDependencies: + stylelint: ^15.3.0 + dependencies: + stylelint: 15.11.0(typescript@5.1.6) + dev: true + + /stylelint-config-standard-scss@8.0.0(postcss@8.4.31)(stylelint@15.11.0): + resolution: {integrity: sha512-TDT/gJD/0LUDoUgkjF1uoI/4DfczXHxg7gJVcWT4/JbE6k5hszVuI14reNX+tEwSyMNhcK2BA7izrK+uVAz7XA==} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^15.4.0 + peerDependenciesMeta: + postcss: + optional: true + dependencies: + postcss: 8.4.31 + stylelint: 15.11.0(typescript@5.1.6) + stylelint-config-recommended-scss: 10.0.0(postcss@8.4.31)(stylelint@15.11.0) + stylelint-config-standard: 32.0.0(stylelint@15.11.0) + dev: true + + /stylelint-config-standard@32.0.0(stylelint@15.11.0): + resolution: {integrity: sha512-UnGJxYDyYFrIE9CjDMZRkrNh2o4lOtO+MVZ9qG5b8yARfsWho0GMx4YvhHfsv8zKKgHeWX2wfeyxmuoqcaYZ4w==} + peerDependencies: + stylelint: ^15.4.0 + dependencies: + stylelint: 15.11.0(typescript@5.1.6) + stylelint-config-recommended: 11.0.0(stylelint@15.11.0) + dev: true + + /stylelint-scss@4.7.0(stylelint@15.11.0): + resolution: {integrity: sha512-TSUgIeS0H3jqDZnby1UO1Qv3poi1N8wUYIJY6D1tuUq2MN3lwp/rITVo0wD+1SWTmRm0tNmGO0b7nKInnqF6Hg==} + peerDependencies: + stylelint: ^14.5.1 || ^15.0.0 + dependencies: + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.1 + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + stylelint: 15.11.0(typescript@5.1.6) + dev: true + + /stylelint@15.11.0(typescript@5.1.6): + resolution: {integrity: sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==} + engines: {node: ^14.13.1 || >=16.0.0} + hasBin: true + dependencies: + '@csstools/css-parser-algorithms': 2.3.2(@csstools/css-tokenizer@2.2.1) + '@csstools/css-tokenizer': 2.2.1 + '@csstools/media-query-list-parser': 2.1.5(@csstools/css-parser-algorithms@2.3.2)(@csstools/css-tokenizer@2.2.1) + '@csstools/selector-specificity': 3.0.0(postcss-selector-parser@6.0.13) + balanced-match: 2.0.0 + colord: 2.9.3 + cosmiconfig: 8.3.6(typescript@5.1.6) + css-functions-list: 3.2.1 + css-tree: 2.3.1 + debug: 4.3.4 + fast-glob: 3.3.2 + fastest-levenshtein: 1.0.16 + file-entry-cache: 7.0.1 + global-modules: 2.0.0 + globby: 11.1.0 + globjoin: 0.1.4 + html-tags: 3.3.1 + ignore: 5.2.4 + import-lazy: 4.0.0 + imurmurhash: 0.1.4 + is-plain-object: 5.0.0 + known-css-properties: 0.29.0 + mathml-tag-names: 2.1.3 + meow: 10.1.5 + micromatch: 4.0.5 + normalize-path: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.31 + postcss-resolve-nested-selector: 0.1.1 + postcss-safe-parser: 6.0.0(postcss@8.4.31) + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + resolve-from: 5.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + style-search: 0.1.0 + supports-hyperlinks: 3.0.0 + svg-tags: 1.0.0 + table: 6.8.1 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks@3.0.0: + resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} + engines: {node: '>=14.18'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + dev: true + + /symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + dev: true + + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} + dependencies: + ajv: 8.12.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: true + + /tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /tar@6.2.0: + resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + + /terser-webpack-plugin@5.3.9(esbuild@0.18.17)(webpack@5.88.2): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + esbuild: 0.18.17 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.19.2 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /terser-webpack-plugin@5.3.9(webpack@5.88.2): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.19.2 + webpack: 5.88.2 + dev: true + + /terser@5.19.2: + resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.11.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-extensions@1.9.0: + resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} + engines: {node: '>=0.10'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.2 + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /tmp@0.2.1: + resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} + engines: {node: '>=8.17.0'} + dependencies: + rimraf: 3.0.2 + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: true + + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + + /tr46@2.1.0: + resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} + engines: {node: '>=8'} + dependencies: + punycode: 2.3.1 + dev: true + + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + + /trim-newlines@4.1.1: + resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} + engines: {node: '>=12'} + dev: true + + /ts-node@10.9.1(@types/node@18.18.9)(typescript@5.1.6): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.18.9 + acorn: 8.11.2 + acorn-walk: 8.3.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.1.6 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /tsconfig-paths@3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.6.1: + resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + /tsutils@3.21.0(typescript@5.1.6): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.1.6 + dev: true + + /tuf-js@1.1.7: + resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@tufjs/models': 1.0.4 + debug: 4.3.4 + make-fetch-happen: 11.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true + + /type-fest@4.6.0: + resolution: {integrity: sha512-rLjWJzQFOq4xw7MgJrCZ6T1jIOvvYElXT12r+y0CC6u67hegDHaxcPqb2fZHOGlqxugGQPNB1EnTezjBetkwkw==} + engines: {node: '>=16'} + dev: false + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: true + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typed-assert@1.0.9: + resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==} + dev: true + + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /ua-parser-js@0.7.37: + resolution: {integrity: sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==} + dev: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + dependencies: + buffer: 5.7.1 + through: 2.3.8 + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: true + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-property-aliases-ecmascript: 2.1.0 + dev: true + + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + unique-slug: 3.0.0 + dev: true + + /unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + unique-slug: 4.0.0 + dev: true + + /unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + dev: true + + /unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + dev: true + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.22.1): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.1 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: true + + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /v8-compile-cache@2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /validate-npm-package-name@5.0.0: + resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + builtins: 5.0.1 + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: true + + /vite@4.4.7(@types/node@18.18.9)(less@4.1.3)(sass@1.64.1)(terser@5.19.2): + resolution: {integrity: sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.18.9 + esbuild: 0.18.17 + less: 4.1.3 + postcss: 8.4.31 + rollup: 3.29.4 + sass: 1.64.1 + terser: 5.19.2 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /void-elements@2.0.1: + resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} + engines: {node: '>=0.10.0'} + dev: true + + /w3c-hr-time@1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + deprecated: Use your platform's native performance.now() and performance.timeOrigin. + dependencies: + browser-process-hrtime: 1.0.0 + dev: true + + /w3c-xmlserializer@2.0.0: + resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} + engines: {node: '>=10'} + dependencies: + xml-name-validator: 3.0.0 + dev: true + + /watchpack@2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: true + + /wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + dependencies: + minimalistic-assert: 1.0.1 + dev: true + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + + /webidl-conversions@5.0.0: + resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} + engines: {node: '>=8'} + dev: true + + /webidl-conversions@6.1.0: + resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==} + engines: {node: '>=10.4'} + dev: true + + /webpack-dev-middleware@5.3.3(webpack@5.88.2): + resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.2.0 + webpack: 5.88.2 + dev: true + + /webpack-dev-middleware@6.1.1(webpack@5.88.2): + resolution: {integrity: sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.2.0 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /webpack-dev-server@4.15.1(webpack@5.88.2): + resolution: {integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==} + engines: {node: '>= 12.13.0'} + hasBin: true + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.3 + '@types/express': 4.17.21 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.5 + '@types/sockjs': 0.3.36 + '@types/ws': 8.5.9 + ansi-html-community: 0.0.8 + bonjour-service: 1.1.1 + chokidar: 3.5.3 + colorette: 2.0.20 + compression: 1.7.4 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.18.2 + graceful-fs: 4.2.11 + html-entities: 2.4.0 + http-proxy-middleware: 2.0.6(@types/express@4.17.21) + ipaddr.js: 2.1.0 + launch-editor: 2.6.1 + open: 8.4.2 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.2.0 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack: 5.88.2 + webpack-dev-middleware: 5.3.3(webpack@5.88.2) + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: true + + /webpack-merge@5.10.0: + resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} + engines: {node: '>=10.0.0'} + dependencies: + clone-deep: 4.0.1 + flat: 5.0.2 + wildcard: 2.0.1 + dev: true + + /webpack-merge@5.9.0: + resolution: {integrity: sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==} + engines: {node: '>=10.0.0'} + dependencies: + clone-deep: 4.0.1 + wildcard: 2.0.1 + dev: true + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack-subresource-integrity@5.1.0(webpack@5.88.2): + resolution: {integrity: sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==} + engines: {node: '>= 12'} + peerDependencies: + html-webpack-plugin: '>= 5.0.0-beta.1 < 6' + webpack: ^5.12.0 + peerDependenciesMeta: + html-webpack-plugin: + optional: true + dependencies: + typed-assert: 1.0.9 + webpack: 5.88.2(esbuild@0.18.17) + dev: true + + /webpack@5.88.2: + resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.11.2 + acorn-import-assertions: 1.9.0(acorn@8.11.2) + browserslist: 4.22.1 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.9(webpack@5.88.2) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /webpack@5.88.2(esbuild@0.18.17): + resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.11.2 + acorn-import-assertions: 1.9.0(acorn@8.11.2) + browserslist: 4.22.1 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.9(esbuild@0.18.17)(webpack@5.88.2) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + dependencies: + http-parser-js: 0.5.8 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + dev: true + + /websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + dev: true + + /whatwg-encoding@1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + dependencies: + iconv-lite: 0.4.24 + dev: true + + /whatwg-mimetype@2.3.0: + resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} + dev: true + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /whatwg-url@8.7.0: + resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} + engines: {node: '>=10'} + dependencies: + lodash: 4.17.21 + tr46: 2.1.0 + webidl-conversions: 6.1.0 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: true + + /wildcard@2.0.1: + resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + dev: true + + /ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /ws@8.11.0: + resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} + 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 + dev: true + + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + 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 + dev: true + + /ws@8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + 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 + dev: true + + /xml-name-validator@3.0.0: + resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} + dev: true + + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: true + + /yargs@17.7.1: + resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: true + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + + /zone.js@0.13.3: + resolution: {integrity: sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==} + dependencies: + tslib: 2.6.2 + + file:src/exported: + resolution: {directory: src/exported, type: directory} + name: '@ae_utbm/typings' + dependencies: + type-fest: 4.6.0 + dev: false diff --git a/src/app-routing.module.ts b/src/app-routing.module.ts new file mode 100644 index 0000000..87b9188 --- /dev/null +++ b/src/app-routing.module.ts @@ -0,0 +1,121 @@ +import { NgModule, inject } from '@angular/core'; +import { Route, RouterModule } from '@angular/router'; + +import { AuthGuard } from '@guards/auth.guard'; +import { NotFoundComponent } from '@pages/404/not-found.component'; +import { ForgotPasswordComponent } from '@pages/forgot_password/forgot_password.component'; +import { HomeComponent } from '@pages/home/home.component'; +import { LoginComponent } from '@pages/login/login.component'; +import { RegisterComponent } from '@pages/register/register.component'; +import { UserProfileComponent } from '@pages/user/profile/profile.component'; +import { VerifyComponent } from '@pages/verify/verify.component'; +import { LangKeys } from '@utils/i18n'; + +export type RouteData = { + full_width?: boolean; + headless?: boolean; + title?: LangKeys; +}; + +const routes: Array & { data?: RouteData }> = [ + { + path: '', + redirectTo: '/home', + pathMatch: 'full', + }, + { + path: 'home', + component: HomeComponent, + data: { + title: 'home.title', + }, + }, + { + path: '404', + component: NotFoundComponent, + data: { + headless: true, + title: '404.title', + }, + }, + { + path: 'login', + canActivate: [() => inject(AuthGuard).isLoggedOut()], + component: LoginComponent, + data: { + headless: true, + title: 'login.title', + }, + }, + { + path: 'register', + canActivate: [() => inject(AuthGuard).isLoggedOut()], + component: RegisterComponent, + data: { + headless: true, + title: 'register.title', + }, + }, + { + path: 'forgot_password', + canActivate: [() => inject(AuthGuard).isLoggedOut()], + component: ForgotPasswordComponent, + data: { + headless: true, + title: 'forgot_password.title', + }, + }, + { + path: 'verify', + canActivate: [() => inject(AuthGuard).isLoggedOut()], + component: VerifyComponent, + data: { + headless: true, + title: 'verify.page_title', + }, + }, + { + path: 'users', + canActivate: [() => inject(AuthGuard).isLoggedIn()], + children: [ + { + path: ':id', + children: [ + { + path: '', + redirectTo: 'profile', + pathMatch: 'prefix', + }, + { + path: 'profile', + component: UserProfileComponent, + pathMatch: 'full', + }, + // { + // path: 'pictures', + // component: UserPicturesComponent, + // }, + // { + // path: 'payments', + // component: UserPaymentsComponent, + // canActivate: [ + // (route: ActivatedRouteSnapshot) => + // inject(UserPermissionService).canReadPrivateUser(parseInt(route.params['id'], 10)), + // ], + // }, + ], + }, + ], + }, + { + path: '**', + redirectTo: '404', + pathMatch: 'full', + }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/src/app.component.html b/src/app.component.html new file mode 100644 index 0000000..3ac33fc --- /dev/null +++ b/src/app.component.html @@ -0,0 +1,15 @@ +
+ + + +
+ + + +
+ + +
+
+ + diff --git a/src/app.component.scss b/src/app.component.scss new file mode 100644 index 0000000..1e83f4a --- /dev/null +++ b/src/app.component.scss @@ -0,0 +1,19 @@ +main { + max-width: var(--max-page-width); + width: 100%; + margin: 0 auto; + padding: 20px 0; + display: flex; + flex-direction: column; + gap: 30px; + + &.headless { + margin: 0; + max-width: none; + padding: 0; + } +} + +router-outlet { + display: none; +} diff --git a/src/app.component.ts b/src/app.component.ts new file mode 100644 index 0000000..e5cef78 --- /dev/null +++ b/src/app.component.ts @@ -0,0 +1,23 @@ +import { DOCUMENT } from '@angular/common'; +import { Component, Inject } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-root', + templateUrl: './app.component.html', + styleUrls: [], +}) +export class AppComponent { + public title = 'sith4'; + public alerts = { + all: [], + }; + + public constructor( + @Inject(TranslateService) public readonly translate: TranslateService, + @Inject(PageService) public readonly page: PageService, + @Inject(DOCUMENT) public readonly document: Document, + ) {} +} diff --git a/src/app.module.ts b/src/app.module.ts new file mode 100644 index 0000000..610661f --- /dev/null +++ b/src/app.module.ts @@ -0,0 +1,39 @@ +import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { NgHcaptchaModule } from 'ng-hcaptcha'; + +import { ComponentsModule } from '@components/components.module'; +import { environment } from '@environments/environment.dev'; +import { AuthGuard } from '@guards/auth.guard'; +import { PagesModule } from '@pages/pages.module'; +import { HttpLoaderFactory } from '@utils/i18n'; + +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [AppComponent], + imports: [ + AppRoutingModule, + BrowserModule, + ComponentsModule, + PagesModule, + HttpClientModule, + TranslateModule.forRoot({ + defaultLanguage: 'en-US', + loader: { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpClient], + }, + }), + NgHcaptchaModule.forRoot({ + siteKey: environment.HCAPTCHA_SITE_KEY, + }), + ], + providers: [AuthGuard], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/src/assets/favicon/base/android-chrome-192x192.png b/src/assets/favicon/base/android-chrome-192x192.png new file mode 100644 index 0000000..d0b9a82 Binary files /dev/null and b/src/assets/favicon/base/android-chrome-192x192.png differ diff --git a/src/assets/favicon/base/android-chrome-512x512.png b/src/assets/favicon/base/android-chrome-512x512.png new file mode 100644 index 0000000..284c4a4 Binary files /dev/null and b/src/assets/favicon/base/android-chrome-512x512.png differ diff --git a/src/assets/favicon/base/apple-touch-icon.png b/src/assets/favicon/base/apple-touch-icon.png new file mode 100644 index 0000000..e28c5f2 Binary files /dev/null and b/src/assets/favicon/base/apple-touch-icon.png differ diff --git a/src/assets/favicon/base/browserconfig.xml b/src/assets/favicon/base/browserconfig.xml new file mode 100644 index 0000000..5cda031 --- /dev/null +++ b/src/assets/favicon/base/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #00aba9 + + + diff --git a/src/assets/favicon/base/favicon-16x16.png b/src/assets/favicon/base/favicon-16x16.png new file mode 100644 index 0000000..1a68103 Binary files /dev/null and b/src/assets/favicon/base/favicon-16x16.png differ diff --git a/src/assets/favicon/base/favicon-32x32.png b/src/assets/favicon/base/favicon-32x32.png new file mode 100644 index 0000000..2fdba59 Binary files /dev/null and b/src/assets/favicon/base/favicon-32x32.png differ diff --git a/src/assets/favicon/base/favicon.ico b/src/assets/favicon/base/favicon.ico new file mode 100644 index 0000000..a7fa7de Binary files /dev/null and b/src/assets/favicon/base/favicon.ico differ diff --git a/src/assets/favicon/base/mstile-150x150.png b/src/assets/favicon/base/mstile-150x150.png new file mode 100644 index 0000000..c6f9343 Binary files /dev/null and b/src/assets/favicon/base/mstile-150x150.png differ diff --git a/src/assets/favicon/base/safari-pinned-tab.svg b/src/assets/favicon/base/safari-pinned-tab.svg new file mode 100644 index 0000000..00db516 --- /dev/null +++ b/src/assets/favicon/base/safari-pinned-tab.svg @@ -0,0 +1,47 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + + + + + diff --git a/src/assets/favicon/base/site.webmanifest b/src/assets/favicon/base/site.webmanifest new file mode 100644 index 0000000..99a81e3 --- /dev/null +++ b/src/assets/favicon/base/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "AE", + "short_name": "AE", + "icons": [ + { + "src": "/assets/favicon/base/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/assets/favicon/base/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/src/assets/favicon/christmas/android-chrome-192x192.png b/src/assets/favicon/christmas/android-chrome-192x192.png new file mode 100644 index 0000000..7b31e81 Binary files /dev/null and b/src/assets/favicon/christmas/android-chrome-192x192.png differ diff --git a/src/assets/favicon/christmas/android-chrome-512x512.png b/src/assets/favicon/christmas/android-chrome-512x512.png new file mode 100644 index 0000000..35cffe1 Binary files /dev/null and b/src/assets/favicon/christmas/android-chrome-512x512.png differ diff --git a/src/assets/favicon/christmas/apple-touch-icon.png b/src/assets/favicon/christmas/apple-touch-icon.png new file mode 100644 index 0000000..ca70eae Binary files /dev/null and b/src/assets/favicon/christmas/apple-touch-icon.png differ diff --git a/src/assets/favicon/christmas/browserconfig.xml b/src/assets/favicon/christmas/browserconfig.xml new file mode 100644 index 0000000..fac4ff4 --- /dev/null +++ b/src/assets/favicon/christmas/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #095228 + + + diff --git a/src/assets/favicon/christmas/favicon-16x16.png b/src/assets/favicon/christmas/favicon-16x16.png new file mode 100644 index 0000000..2ff22da Binary files /dev/null and b/src/assets/favicon/christmas/favicon-16x16.png differ diff --git a/src/assets/favicon/christmas/favicon-32x32.png b/src/assets/favicon/christmas/favicon-32x32.png new file mode 100644 index 0000000..80209b1 Binary files /dev/null and b/src/assets/favicon/christmas/favicon-32x32.png differ diff --git a/src/assets/favicon/christmas/favicon.ico b/src/assets/favicon/christmas/favicon.ico new file mode 100644 index 0000000..8548b01 Binary files /dev/null and b/src/assets/favicon/christmas/favicon.ico differ diff --git a/src/assets/favicon/christmas/mstile-150x150.png b/src/assets/favicon/christmas/mstile-150x150.png new file mode 100644 index 0000000..d2ec2c6 Binary files /dev/null and b/src/assets/favicon/christmas/mstile-150x150.png differ diff --git a/src/assets/favicon/christmas/safari-pinned-tab.svg b/src/assets/favicon/christmas/safari-pinned-tab.svg new file mode 100644 index 0000000..250462e --- /dev/null +++ b/src/assets/favicon/christmas/safari-pinned-tab.svg @@ -0,0 +1,108 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/favicon/christmas/site.webmanifest b/src/assets/favicon/christmas/site.webmanifest new file mode 100644 index 0000000..78c3643 --- /dev/null +++ b/src/assets/favicon/christmas/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "AE", + "short_name": "AE", + "icons": [ + { + "src": "/assets/favicon/christmas/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/assets/favicon/christmas/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#095228", + "background_color": "#095228", + "display": "standalone" +} diff --git a/src/assets/favicon/pinktober/android-chrome-192x192.png b/src/assets/favicon/pinktober/android-chrome-192x192.png new file mode 100644 index 0000000..3677a82 Binary files /dev/null and b/src/assets/favicon/pinktober/android-chrome-192x192.png differ diff --git a/src/assets/favicon/pinktober/android-chrome-512x512.png b/src/assets/favicon/pinktober/android-chrome-512x512.png new file mode 100644 index 0000000..b81cd88 Binary files /dev/null and b/src/assets/favicon/pinktober/android-chrome-512x512.png differ diff --git a/src/assets/favicon/pinktober/apple-touch-icon.png b/src/assets/favicon/pinktober/apple-touch-icon.png new file mode 100644 index 0000000..138080f Binary files /dev/null and b/src/assets/favicon/pinktober/apple-touch-icon.png differ diff --git a/src/assets/favicon/pinktober/browserconfig.xml b/src/assets/favicon/pinktober/browserconfig.xml new file mode 100644 index 0000000..38b267f --- /dev/null +++ b/src/assets/favicon/pinktober/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #e891dc + + + diff --git a/src/assets/favicon/pinktober/favicon-16x16.png b/src/assets/favicon/pinktober/favicon-16x16.png new file mode 100644 index 0000000..2cc668f Binary files /dev/null and b/src/assets/favicon/pinktober/favicon-16x16.png differ diff --git a/src/assets/favicon/pinktober/favicon-32x32.png b/src/assets/favicon/pinktober/favicon-32x32.png new file mode 100644 index 0000000..f36c475 Binary files /dev/null and b/src/assets/favicon/pinktober/favicon-32x32.png differ diff --git a/src/assets/favicon/pinktober/favicon.ico b/src/assets/favicon/pinktober/favicon.ico new file mode 100644 index 0000000..d07c597 Binary files /dev/null and b/src/assets/favicon/pinktober/favicon.ico differ diff --git a/src/assets/favicon/pinktober/mstile-150x150.png b/src/assets/favicon/pinktober/mstile-150x150.png new file mode 100644 index 0000000..a502e8e Binary files /dev/null and b/src/assets/favicon/pinktober/mstile-150x150.png differ diff --git a/src/assets/favicon/pinktober/safari-pinned-tab.svg b/src/assets/favicon/pinktober/safari-pinned-tab.svg new file mode 100644 index 0000000..8e38a24 --- /dev/null +++ b/src/assets/favicon/pinktober/safari-pinned-tab.svg @@ -0,0 +1,58 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + + + + + diff --git a/src/assets/favicon/pinktober/site.webmanifest b/src/assets/favicon/pinktober/site.webmanifest new file mode 100644 index 0000000..65e0dfa --- /dev/null +++ b/src/assets/favicon/pinktober/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "AE", + "short_name": "AE", + "icons": [ + { + "src": "/assets/favicon/pinktober/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/assets/favicon/pinktober/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#e891dc", + "background_color": "#e891dc", + "display": "standalone" +} diff --git a/src/assets/flags/ar-SA.svg b/src/assets/flags/ar-SA.svg new file mode 100644 index 0000000..ea37929 --- /dev/null +++ b/src/assets/flags/ar-SA.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/flags/de-DE.svg b/src/assets/flags/de-DE.svg new file mode 100644 index 0000000..f104896 --- /dev/null +++ b/src/assets/flags/de-DE.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/flags/en-GB.svg b/src/assets/flags/en-GB.svg new file mode 100644 index 0000000..2e46fd1 --- /dev/null +++ b/src/assets/flags/en-GB.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/flags/es-ES.svg b/src/assets/flags/es-ES.svg new file mode 100644 index 0000000..a59dc6f --- /dev/null +++ b/src/assets/flags/es-ES.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/flags/fr-FR.svg b/src/assets/flags/fr-FR.svg new file mode 100644 index 0000000..e4cee6a --- /dev/null +++ b/src/assets/flags/fr-FR.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/flags/it-IT.svg b/src/assets/flags/it-IT.svg new file mode 100644 index 0000000..bfa30e0 --- /dev/null +++ b/src/assets/flags/it-IT.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/flags/ja-JP.svg b/src/assets/flags/ja-JP.svg new file mode 100644 index 0000000..c94a16d --- /dev/null +++ b/src/assets/flags/ja-JP.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/flags/ru-RU.svg b/src/assets/flags/ru-RU.svg new file mode 100644 index 0000000..efcf3f8 --- /dev/null +++ b/src/assets/flags/ru-RU.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/flags/uk-UA.svg b/src/assets/flags/uk-UA.svg new file mode 100644 index 0000000..d2f9a99 --- /dev/null +++ b/src/assets/flags/uk-UA.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/flags/zh-CN.svg b/src/assets/flags/zh-CN.svg new file mode 100644 index 0000000..2889043 --- /dev/null +++ b/src/assets/flags/zh-CN.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/fonts/Inter/Inter-Black.ttf b/src/assets/fonts/Inter/Inter-Black.ttf new file mode 100644 index 0000000..5aecf7d Binary files /dev/null and b/src/assets/fonts/Inter/Inter-Black.ttf differ diff --git a/src/assets/fonts/Inter/Inter-Bold.ttf b/src/assets/fonts/Inter/Inter-Bold.ttf new file mode 100644 index 0000000..8e82c70 Binary files /dev/null and b/src/assets/fonts/Inter/Inter-Bold.ttf differ diff --git a/src/assets/fonts/Inter/Inter-ExtraBold.ttf b/src/assets/fonts/Inter/Inter-ExtraBold.ttf new file mode 100644 index 0000000..cb4b821 Binary files /dev/null and b/src/assets/fonts/Inter/Inter-ExtraBold.ttf differ diff --git a/src/assets/fonts/Inter/Inter-ExtraLight.ttf b/src/assets/fonts/Inter/Inter-ExtraLight.ttf new file mode 100644 index 0000000..64aee30 Binary files /dev/null and b/src/assets/fonts/Inter/Inter-ExtraLight.ttf differ diff --git a/src/assets/fonts/Inter/Inter-Light.ttf b/src/assets/fonts/Inter/Inter-Light.ttf new file mode 100644 index 0000000..9e265d8 Binary files /dev/null and b/src/assets/fonts/Inter/Inter-Light.ttf differ diff --git a/src/assets/fonts/Inter/Inter-Medium.ttf b/src/assets/fonts/Inter/Inter-Medium.ttf new file mode 100644 index 0000000..b53fb1c Binary files /dev/null and b/src/assets/fonts/Inter/Inter-Medium.ttf differ diff --git a/src/assets/fonts/Inter/Inter-Regular.ttf b/src/assets/fonts/Inter/Inter-Regular.ttf new file mode 100644 index 0000000..8d4eebf Binary files /dev/null and b/src/assets/fonts/Inter/Inter-Regular.ttf differ diff --git a/src/assets/fonts/Inter/Inter-SemiBold.ttf b/src/assets/fonts/Inter/Inter-SemiBold.ttf new file mode 100644 index 0000000..c6aeeb1 Binary files /dev/null and b/src/assets/fonts/Inter/Inter-SemiBold.ttf differ diff --git a/src/assets/fonts/Inter/Inter-Thin.ttf b/src/assets/fonts/Inter/Inter-Thin.ttf new file mode 100644 index 0000000..7aed55d Binary files /dev/null and b/src/assets/fonts/Inter/Inter-Thin.ttf differ diff --git a/src/assets/fonts/Roboto/LICENSE.txt b/src/assets/fonts/Roboto/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/src/assets/fonts/Roboto/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/assets/fonts/Roboto/Roboto-Black.ttf b/src/assets/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 0000000..0112e7d Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Black.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-BlackItalic.ttf b/src/assets/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 0000000..b2c6aca Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-BlackItalic.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-Bold.ttf b/src/assets/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 0000000..43da14d Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-BoldItalic.ttf b/src/assets/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..bcfdab4 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-Italic.ttf b/src/assets/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000..1b5eaa3 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-Light.ttf b/src/assets/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 0000000..e7307e7 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Light.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-LightItalic.ttf b/src/assets/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 0000000..2d277af Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-LightItalic.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-Medium.ttf b/src/assets/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 0000000..ac0f908 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Medium.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-MediumItalic.ttf b/src/assets/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 0000000..fc36a47 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-MediumItalic.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-Regular.ttf b/src/assets/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 0000000..ddf4bfa Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Regular.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-Thin.ttf b/src/assets/fonts/Roboto/Roboto-Thin.ttf new file mode 100644 index 0000000..2e0dee6 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-Thin.ttf differ diff --git a/src/assets/fonts/Roboto/Roboto-ThinItalic.ttf b/src/assets/fonts/Roboto/Roboto-ThinItalic.ttf new file mode 100644 index 0000000..084f9c0 Binary files /dev/null and b/src/assets/fonts/Roboto/Roboto-ThinItalic.ttf differ diff --git a/src/assets/i18n/en-US.json b/src/assets/i18n/en-US.json new file mode 100644 index 0000000..720c0cf --- /dev/null +++ b/src/assets/i18n/en-US.json @@ -0,0 +1,146 @@ +{ + "i18n": { + "switch_lang": "Language selection", + "select_lang": "Select a language", + "help_us_translate": "Help us translate this website" + }, + "navbar": { + "favorites": "Favorites", + "shop": "Shop", + "events": "Events", + "forum": "Forum", + "pictures": "Pictures" + }, + "header": { + "options": { + "title": "Accessibility Parameters", + "themes": { + "title": "Theme selection", + "light": "Light", + "dark": "Dark", + "auto": "Auto", + "high_contrast": "High contrast" + }, + "themes_event": { + "pinktober": "Pinktober", + "christmas": "Christmas" + }, + "font_size": { + "title": "Font size", + "small": "Small", + "medium": "Medium", + "large": "Large" + }, + "accent_color": { + "title": "Accent color" + } + }, + "profile": { + "profile": "Profile", + "pictures": "Pictures", + "payments": "Payments", + "disconnect": "Disconnect" + } + }, + "global": { + "back": "Back", + "sign_in": "Sign in", + "save": "Save", + "cancel": "Cancel", + "delete": "Delete", + "register": "Register", + "last_name": "Last name", + "first_name": "First name", + "email_template": "example@website.com", + "password": "Password", + "confirm_password": "Confirm password", + "date_birth": "Date of birth", + "errors": { + "required": "This field is required", + "forbidden_email": "This email is forbidden", + "age_minimum": "You must be at least {{ min }} years old", + "age_maximum": "You must be at most {{ max }} years old", + "not_in_future": "This date cannot be in the future", + "invalid_name": "This name is invalid", + "has_one_digit": "This password must contain at least one digit", + "has_one_special_character": "This password must contain at least one special character", + "has_one_lowercase": "This password must contain at least one lowercase letter", + "has_one_uppercase": "This password must contain at least one uppercase letter", + "has_no_duplicate_characters": "This password must not contain duplicate characters next to each other", + "passwords_mismatch": "The passwords do not match", + "password_wrong": "Wrong password", + "minlength": "This field must contain at least {{ min }} characters", + "maxlength": "This field must contain at most {{ max }} characters", + "email": "This email is invalid", + "email_not_found": "No user found with this email" + } + }, + "404": { + "title": "Page not found", + "description": "The page you are looking for does not exist or has been moved.", + "return_home": "Return to home page" + }, + "home": { + "title": "Home" + }, + "forgot_password": { + "title": "Forgot password", + "description": "If you have forgotten your password, enter your email address below to reset your password.", + "send_email": "Send email" + }, + "login":{ + "title": "Login", + "no_account": "No account ? Register", + "forgot_password": "Forgot your password ?", + "external_connection": "Or connect with", + "already_logged_as_x": "You are already logged as {{name}}" + }, + "register":{ + "title": "Register", + "already_have_account": "Already have an account ? Log In", + "date_birth_no_modif": "Your date of birth cannot be changed", + "min_password": "Minimum of 8 characters including 1 special", + "confirm_password": "Type your password again", + "already_registered_and_logged_as_x": "You are already registered and logged as {{name}}" + }, + "profile":{ + "about": "About", + "account_suspended": "Account suspended", + "account_banned": "Account banned : {{time}} left", + "age": "{{age}} years old", + "birthday": "Birth date", + "contact": "Contact", + "cursus_utbm": "UTBM Curriculum", + "email": "Email", + "first_name": "First name", + "gender": "Gender", + "identity_info": "Only administrators can change your first name, last name, and date of birth, upon presentation of supporting documentation.", + "joined_the_site": "Joined the site", + "last_name": "Last name", + "last_seen": "Last seen", + "never_seen": "Never seen", + "nickname": "Nickname", + "parent_contact": "Parent contact", + "parent_contact_info": "This field will disappear as soon as you become of legal age. It is only visible to you and the moderators of the website.", + "phone": "Phone", + "picture_too_recent": "You can't change your profile picture before {{date}}", + "pronouns": "Pronouns", + "promotion": "Promotion", + "specialty": "Specialty", + "secondary_email": "Secondary email", + "subscription" : "Subscription date", + "title": "Profile of {{name}}", + "update_picture": "Update your picture", + "update_picture_of_user": "Update picture of {{username}}", + "update_banner": "Update your banner", + "update_banner_of_user": "Update banner of {{username}}", + "update_infos": "Update your informations", + "update_infos_of_user": "Update informations of {{username}}", + "update_permissions_of_user": "Update permissions of {{username}}" + }, + "verify": { + "page_title": "Verify your email address", + "title": "Please verify your email address", + "description": "A verification email has been sent to you. Please click on the link in the email to verify your email address." + } +} diff --git a/src/assets/i18n/fr-FR.json b/src/assets/i18n/fr-FR.json new file mode 100644 index 0000000..2b7ea29 --- /dev/null +++ b/src/assets/i18n/fr-FR.json @@ -0,0 +1,7 @@ +{ + "i18n": { + "switch_lang": "Choix de la langue", + "select_lang": "Sélectionnez une langue", + "help_us_translate": "Aidez-nous à traduire ce site" + } +} diff --git a/src/assets/i18n/languages.json b/src/assets/i18n/languages.json new file mode 100644 index 0000000..d439203 --- /dev/null +++ b/src/assets/i18n/languages.json @@ -0,0 +1,103 @@ +[ + { + "codes": [ + "en", + "en-US", + "en-GB" + ], + "filename": "en-US", + "label": "English", + "image": "assets/flags/en-GB.svg", + "direction": "ltr" + }, + { + "codes": [ + "fr", + "fr-FR" + ], + "filename": "fr-FR", + "label": "Français", + "image": "assets/flags/fr-FR.svg", + "direction": "ltr" + }, + { + "codes": [ + "es", + "es-ES" + ], + "filename": "es-ES", + "label": "Español", + "image": "assets/flags/es-ES.svg", + "direction": "ltr" + }, + { + "codes": [ + "de", + "de-DE" + ], + "filename": "de-DE", + "label": "Deutsch", + "image": "assets/flags/de-DE.svg", + "direction": "ltr" + }, + { + "codes": [ + "it", + "it-IT" + ], + "filename": "it-IT", + "label": "Italiano", + "image": "assets/flags/it-IT.svg", + "direction": "ltr" + }, + { + "codes": [ + "ru", + "ru-RU" + ], + "filename": "ru-RU", + "label": "Русский", + "image": "assets/flags/ru-RU.svg", + "direction": "ltr" + }, + { + "codes": [ + "uk", + "uk-UA" + ], + "filename": "uk-UA", + "label": "Українська", + "image": "assets/flags/uk-UA.svg", + "direction": "ltr" + }, + { + "codes": [ + "zh", + "zh-CN" + ], + "filename": "zh-CN", + "label": "中文", + "image": "assets/flags/zh-CN.svg", + "direction": "ltr" + }, + { + "codes": [ + "ja", + "ja-JP" + ], + "filename": "ja-JP", + "label": "日本語", + "image": "assets/flags/ja-JP.svg", + "direction": "ltr" + }, + { + "codes": [ + "ar", + "ar-SA" + ], + "filename": "ar-SA", + "label": "العربية", + "image": "assets/flags/ar-SA.svg", + "direction": "rtl" + } +] diff --git a/src/assets/logo/ae_base.png b/src/assets/logo/ae_base.png new file mode 100644 index 0000000..00c7b98 Binary files /dev/null and b/src/assets/logo/ae_base.png differ diff --git a/src/assets/logo/ae_base.webp b/src/assets/logo/ae_base.webp new file mode 100644 index 0000000..774aa08 Binary files /dev/null and b/src/assets/logo/ae_base.webp differ diff --git a/src/assets/logo/ae_christmas.png b/src/assets/logo/ae_christmas.png new file mode 100644 index 0000000..c80ee86 Binary files /dev/null and b/src/assets/logo/ae_christmas.png differ diff --git a/src/assets/logo/ae_christmas.webp b/src/assets/logo/ae_christmas.webp new file mode 100644 index 0000000..d1380e1 Binary files /dev/null and b/src/assets/logo/ae_christmas.webp differ diff --git a/src/assets/logo/ae_pinktober.png b/src/assets/logo/ae_pinktober.png new file mode 100644 index 0000000..ccd0315 Binary files /dev/null and b/src/assets/logo/ae_pinktober.png differ diff --git a/src/assets/logo/ae_pinktober.webp b/src/assets/logo/ae_pinktober.webp new file mode 100644 index 0000000..506b35a Binary files /dev/null and b/src/assets/logo/ae_pinktober.webp differ diff --git a/src/components/common/button/button.component.html b/src/components/common/button/button.component.html new file mode 100644 index 0000000..2a3f0e2 --- /dev/null +++ b/src/components/common/button/button.component.html @@ -0,0 +1 @@ + diff --git a/src/components/common/button/button.component.scss b/src/components/common/button/button.component.scss new file mode 100644 index 0000000..43d3098 --- /dev/null +++ b/src/components/common/button/button.component.scss @@ -0,0 +1,52 @@ +button { + background-color: var(--gray4); + color: var(--text-color-dark-bg); + display: flex; + align-items: center; + justify-content: center; + padding: 5px 20px; + width: 100%; + border-radius: 5px; + border: none; + font-family: Inter, sans-serif; + text-transform: uppercase; + cursor: pointer; + + &.large { + height: 40px; + } + + &.medium { + height: 30px; + } + + &.small { + height: 20px; + } + + &:hover { + background-color: var(--gray2); + color: var(--text-color-dynamic); + } + + &:disabled { + background-color: var(--gray2-hover); + color: var(--text-color-dark-bg); + cursor: not-allowed; + } + + &.danger { + background-color: var(--red); + color: var(--text-color-dark-bg); + + &:hover { + background-color: var(--red-hover); + color: var(--text-color-dark-bg); + } + + &:disabled { + background-color: var(--gray2-hover); + color: var(--text-color-dark-bg); + } + } +} diff --git a/src/components/common/button/button.component.spec.ts b/src/components/common/button/button.component.spec.ts new file mode 100644 index 0000000..357c283 --- /dev/null +++ b/src/components/common/button/button.component.spec.ts @@ -0,0 +1,56 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; + +import { ButtonComponent } from './button.component'; + +describe('ButtonComponent', () => { + let component: ButtonComponent; + let fixture: ComponentFixture; + let button: HTMLButtonElement; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ButtonComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ButtonComponent); + component = fixture.componentInstance; + }); + + beforeEach(() => { + button = fixture.debugElement.query(By.css('button')).nativeElement as HTMLButtonElement; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should display the text passed in through the text input', () => { + const buttonText = 'Click me!'; + component.text = buttonText; + fixture.detectChanges(); + expect(button.textContent?.trim()).toBe(buttonText); + }); + + it('should have the appropriate class based on the height input', () => { + component.height = 'small'; + fixture.detectChanges(); + expect(button.classList).toContain('small'); + component.height = 'medium'; + fixture.detectChanges(); + expect(button.classList).not.toContain('small'); + expect(button.classList).not.toContain('large'); + component.height = 'large'; + fixture.detectChanges(); + expect(button.classList).toContain('large'); + }); + + it('should disable the button when the disabled input is true', () => { + component.disabled = true; + fixture.detectChanges(); + expect(button.disabled).toBeTrue(); + component.disabled = false; + fixture.detectChanges(); + expect(button.disabled).toBeFalse(); + }); +}); diff --git a/src/components/common/button/button.component.ts b/src/components/common/button/button.component.ts new file mode 100644 index 0000000..afbc20f --- /dev/null +++ b/src/components/common/button/button.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'sith-button', + templateUrl: './button.component.html', + styleUrls: ['./button.component.scss'], +}) +export class ButtonComponent { + @Input() public text = ''; + @Input() public height: 'medium' | 'large' | 'small' = 'medium'; + @Input() public disabled = false; + @Input() public aspect: 'normal' | 'danger' = 'normal'; +} diff --git a/src/components/common/common.module.ts b/src/components/common/common.module.ts new file mode 100644 index 0000000..454cedb --- /dev/null +++ b/src/components/common/common.module.ts @@ -0,0 +1,61 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; + +import { ButtonComponent } from './button/button.component'; +import { IconsModule } from './icons/icons.module'; +import { ImageCropperComponent } from './image_cropper/image-cropper.component'; +import { FileInputComponent } from './inputs/file_input/file-input.component'; +import { PasswordInputComponent } from './inputs/password_input/pass-input.component'; +import { FontSizeSelectorComponent } from './selectors/font_size/font_size_selector.component'; +import { LangSelectorComponent } from './selectors/lang/lang_selector.component'; +import { SelectComponent } from './selectors/select/select.component'; +import { ThemeSelectorComponent } from './selectors/theme/theme_selector.component'; +import { SideMenuDisconnectedComponent } from './side_menu/side_disconnected/side_disconnected.component'; +import { SideMenuComponent } from './side_menu/side_menu.component'; +import { SideMenuOptionsComponent } from './side_menu/side_options/side_options.component'; +import { SideMenuProfileComponent } from './side_menu/side_profile/side_profile.component'; +import { SnackbarComponent } from './snackbar/snackbar.component'; +import { SubtitleComponent } from './subtitle/subtitle.component'; +import { TitleComponent } from './title/title.component'; + +@NgModule({ + declarations: [ + SelectComponent, + ButtonComponent, + SideMenuComponent, + SideMenuOptionsComponent, + SideMenuProfileComponent, + SideMenuDisconnectedComponent, + LangSelectorComponent, + TitleComponent, + SubtitleComponent, + ThemeSelectorComponent, + FontSizeSelectorComponent, + ImageCropperComponent, + FileInputComponent, + SnackbarComponent, + PasswordInputComponent, + ], + exports: [ + IconsModule, + SelectComponent, + ButtonComponent, + SideMenuComponent, + SideMenuOptionsComponent, + SideMenuProfileComponent, + SideMenuDisconnectedComponent, + LangSelectorComponent, + TitleComponent, + SubtitleComponent, + ThemeSelectorComponent, + FontSizeSelectorComponent, + ImageCropperComponent, + FileInputComponent, + SnackbarComponent, + PasswordInputComponent, + ], + imports: [IconsModule, CommonModule, TranslateModule, FormsModule], +}) +export class CommonComponentsModule {} diff --git a/src/components/common/icons/at/at.component.ts b/src/components/common/icons/at/at.component.ts new file mode 100644 index 0000000..deb8469 --- /dev/null +++ b/src/components/common/icons/at/at.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-at', + templateUrl: './at.svg', + styleUrls: ['../icons.scss'], +}) +export class IconAtComponent {} diff --git a/src/components/common/icons/at/at.svg b/src/components/common/icons/at/at.svg new file mode 100644 index 0000000..51d1cdd --- /dev/null +++ b/src/components/common/icons/at/at.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/burger_menu/burger_menu.component.ts b/src/components/common/icons/burger_menu/burger_menu.component.ts new file mode 100644 index 0000000..9e184a6 --- /dev/null +++ b/src/components/common/icons/burger_menu/burger_menu.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-burger-menu', + templateUrl: './burger_menu.svg', + styleUrls: ['../icons.scss'], +}) +export class IconBurgerMenuComponent {} diff --git a/src/components/common/icons/burger_menu/burger_menu.svg b/src/components/common/icons/burger_menu/burger_menu.svg new file mode 100644 index 0000000..d8d5ca4 --- /dev/null +++ b/src/components/common/icons/burger_menu/burger_menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/calendar/calendar.component.ts b/src/components/common/icons/calendar/calendar.component.ts new file mode 100644 index 0000000..f6cdad0 --- /dev/null +++ b/src/components/common/icons/calendar/calendar.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-calendar', + templateUrl: './calendar.svg', + styleUrls: ['../icons.scss'], +}) +export class IconCalendarComponent {} diff --git a/src/components/common/icons/calendar/calendar.svg b/src/components/common/icons/calendar/calendar.svg new file mode 100644 index 0000000..3c4935e --- /dev/null +++ b/src/components/common/icons/calendar/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/close/close.component.ts b/src/components/common/icons/close/close.component.ts new file mode 100644 index 0000000..324c72c --- /dev/null +++ b/src/components/common/icons/close/close.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-close', + templateUrl: './close.svg', + styleUrls: ['../icons.scss'], +}) +export class IconCloseComponent {} diff --git a/src/components/common/icons/close/close.svg b/src/components/common/icons/close/close.svg new file mode 100644 index 0000000..8570240 --- /dev/null +++ b/src/components/common/icons/close/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/cogwheel/cogwheel.component.ts b/src/components/common/icons/cogwheel/cogwheel.component.ts new file mode 100644 index 0000000..a483e23 --- /dev/null +++ b/src/components/common/icons/cogwheel/cogwheel.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-cogwheel', + templateUrl: './cogwheel.svg', + styleUrls: ['../icons.scss'], +}) +export class IconCogwheelComponent {} diff --git a/src/components/common/icons/cogwheel/cogwheel.svg b/src/components/common/icons/cogwheel/cogwheel.svg new file mode 100644 index 0000000..777ec6e --- /dev/null +++ b/src/components/common/icons/cogwheel/cogwheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/expand_less/expand_less.component.ts b/src/components/common/icons/expand_less/expand_less.component.ts new file mode 100644 index 0000000..d100111 --- /dev/null +++ b/src/components/common/icons/expand_less/expand_less.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-expand-less', + templateUrl: './expand_less.svg', + styleUrls: ['../icons.scss'], +}) +export class IconExpandLessComponent {} diff --git a/src/components/common/icons/expand_less/expand_less.svg b/src/components/common/icons/expand_less/expand_less.svg new file mode 100644 index 0000000..143fb9b --- /dev/null +++ b/src/components/common/icons/expand_less/expand_less.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/expand_more/expand_more.component.ts b/src/components/common/icons/expand_more/expand_more.component.ts new file mode 100644 index 0000000..4574184 --- /dev/null +++ b/src/components/common/icons/expand_more/expand_more.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-expand-more', + templateUrl: './expand_more.svg', + styleUrls: ['../icons.scss'], +}) +export class IconExpandMoreComponent {} diff --git a/src/components/common/icons/expand_more/expand_more.svg b/src/components/common/icons/expand_more/expand_more.svg new file mode 100644 index 0000000..bf01c16 --- /dev/null +++ b/src/components/common/icons/expand_more/expand_more.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/eye/eye.component.ts b/src/components/common/icons/eye/eye.component.ts new file mode 100644 index 0000000..932818f --- /dev/null +++ b/src/components/common/icons/eye/eye.component.ts @@ -0,0 +1,10 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'sith-icon-eye', + templateUrl: './eye.svg', + styleUrls: ['../icons.scss'], +}) +export class IconEyeComponent { + @Input() public open = true; +} diff --git a/src/components/common/icons/eye/eye.svg b/src/components/common/icons/eye/eye.svg new file mode 100644 index 0000000..52e03b8 --- /dev/null +++ b/src/components/common/icons/eye/eye.svg @@ -0,0 +1,2 @@ + + diff --git a/src/components/common/icons/flag/flag.component.ts b/src/components/common/icons/flag/flag.component.ts new file mode 100644 index 0000000..955b60d --- /dev/null +++ b/src/components/common/icons/flag/flag.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-flag', + templateUrl: './flag.svg', + styleUrls: ['../icons.scss'], +}) +export class IconFlagComponent {} diff --git a/src/components/common/icons/flag/flag.svg b/src/components/common/icons/flag/flag.svg new file mode 100644 index 0000000..e65a3aa --- /dev/null +++ b/src/components/common/icons/flag/flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/heart_plus/heart_plus.component.ts b/src/components/common/icons/heart_plus/heart_plus.component.ts new file mode 100644 index 0000000..6e6806d --- /dev/null +++ b/src/components/common/icons/heart_plus/heart_plus.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-heart-plus', + templateUrl: './heart_plus.svg', + styleUrls: ['../icons.scss'], +}) +export class IconHeartPlusComponent {} diff --git a/src/components/common/icons/heart_plus/heart_plus.svg b/src/components/common/icons/heart_plus/heart_plus.svg new file mode 100644 index 0000000..b0002fb --- /dev/null +++ b/src/components/common/icons/heart_plus/heart_plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/icons.module.ts b/src/components/common/icons/icons.module.ts new file mode 100644 index 0000000..e93f338 --- /dev/null +++ b/src/components/common/icons/icons.module.ts @@ -0,0 +1,84 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { IconAtComponent } from './at/at.component'; +import { IconBurgerMenuComponent } from './burger_menu/burger_menu.component'; +import { IconCalendarComponent } from './calendar/calendar.component'; +import { IconCloseComponent } from './close/close.component'; +import { IconCogwheelComponent } from './cogwheel/cogwheel.component'; +import { IconExpandLessComponent } from './expand_less/expand_less.component'; +import { IconExpandMoreComponent } from './expand_more/expand_more.component'; +import { IconEyeComponent } from './eye/eye.component'; +import { IconFlagComponent } from './flag/flag.component'; +import { IconHeartPlusComponent } from './heart_plus/heart_plus.component'; +import { IconLaundryComponent } from './laundry/laundry.component'; +import { IconMessagesComponent } from './messages/messages.component'; +import { IconPartyHatComponent } from './party_hat/party_hat.component'; +import { IconPasswordComponent } from './password/password.component'; +import { IconPaymentsComponent } from './payments/payments.component'; +import { IconPencilComponent } from './pencil/pencil.component'; +import { IconPersonComponent } from './person/person.component'; +import { IconPicturesComponent } from './pictures/pictures.component'; +import { IconPromotionComponent } from './promo_icon/promo_icon.component'; +import { IconSearchComponent } from './search/search.component'; +import { IconShoppingBasketComponent } from './shopping_basket/shopping_basket.component'; +import { IconShoppingCartComponent } from './shopping_cart/shopping_cart.component'; +import { IconUploadComponent } from './upload/upload.component'; +import { IconUserComponent } from './user_icon/user_icon.component'; + +@NgModule({ + declarations: [ + IconBurgerMenuComponent, + IconCogwheelComponent, + IconUserComponent, + IconPromotionComponent, + IconExpandLessComponent, + IconExpandMoreComponent, + IconHeartPlusComponent, + IconLaundryComponent, + IconMessagesComponent, + IconPartyHatComponent, + IconPicturesComponent, + IconSearchComponent, + IconShoppingBasketComponent, + IconShoppingCartComponent, + IconPersonComponent, + IconPaymentsComponent, + IconAtComponent, + IconPasswordComponent, + IconCalendarComponent, + IconCloseComponent, + IconPencilComponent, + IconFlagComponent, + IconUploadComponent, + IconEyeComponent, + ], + exports: [ + IconBurgerMenuComponent, + IconCogwheelComponent, + IconUserComponent, + IconPromotionComponent, + IconExpandLessComponent, + IconExpandMoreComponent, + IconHeartPlusComponent, + IconLaundryComponent, + IconMessagesComponent, + IconPartyHatComponent, + IconPicturesComponent, + IconSearchComponent, + IconShoppingBasketComponent, + IconShoppingCartComponent, + IconPersonComponent, + IconPaymentsComponent, + IconAtComponent, + IconPasswordComponent, + IconCalendarComponent, + IconCloseComponent, + IconPencilComponent, + IconFlagComponent, + IconUploadComponent, + IconEyeComponent, + ], + imports: [CommonModule], +}) +export class IconsModule {} diff --git a/src/components/common/icons/icons.scss b/src/components/common/icons/icons.scss new file mode 100644 index 0000000..0c466d6 --- /dev/null +++ b/src/components/common/icons/icons.scss @@ -0,0 +1,7 @@ +svg { + width: 100%; + height: 100%; + + max-width: 100%; + max-height: 100%; +} diff --git a/src/components/common/icons/laundry/laundry.component.ts b/src/components/common/icons/laundry/laundry.component.ts new file mode 100644 index 0000000..470acee --- /dev/null +++ b/src/components/common/icons/laundry/laundry.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-laundry', + templateUrl: './laundry.svg', + styleUrls: ['../icons.scss'], +}) +export class IconLaundryComponent {} diff --git a/src/components/common/icons/laundry/laundry.svg b/src/components/common/icons/laundry/laundry.svg new file mode 100644 index 0000000..f836b0b --- /dev/null +++ b/src/components/common/icons/laundry/laundry.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/messages/messages.component.ts b/src/components/common/icons/messages/messages.component.ts new file mode 100644 index 0000000..b80a5c6 --- /dev/null +++ b/src/components/common/icons/messages/messages.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-messages', + templateUrl: './messages.svg', + styleUrls: ['../icons.scss'], +}) +export class IconMessagesComponent {} diff --git a/src/components/common/icons/messages/messages.svg b/src/components/common/icons/messages/messages.svg new file mode 100644 index 0000000..16a1ef4 --- /dev/null +++ b/src/components/common/icons/messages/messages.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/party_hat/party_hat.component.ts b/src/components/common/icons/party_hat/party_hat.component.ts new file mode 100644 index 0000000..fbcb9fc --- /dev/null +++ b/src/components/common/icons/party_hat/party_hat.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-party-hat', + templateUrl: './party_hat.svg', + styleUrls: ['../icons.scss'], +}) +export class IconPartyHatComponent {} diff --git a/src/components/common/icons/party_hat/party_hat.svg b/src/components/common/icons/party_hat/party_hat.svg new file mode 100644 index 0000000..564b61d --- /dev/null +++ b/src/components/common/icons/party_hat/party_hat.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/password/password.component.ts b/src/components/common/icons/password/password.component.ts new file mode 100644 index 0000000..f22eb9f --- /dev/null +++ b/src/components/common/icons/password/password.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-password', + templateUrl: './password.svg', + styleUrls: ['../icons.scss'], +}) +export class IconPasswordComponent {} diff --git a/src/components/common/icons/password/password.svg b/src/components/common/icons/password/password.svg new file mode 100644 index 0000000..a640596 --- /dev/null +++ b/src/components/common/icons/password/password.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/payments/payments.component.ts b/src/components/common/icons/payments/payments.component.ts new file mode 100644 index 0000000..52040be --- /dev/null +++ b/src/components/common/icons/payments/payments.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-payments', + templateUrl: './payments.svg', + styleUrls: ['../icons.scss'], +}) +export class IconPaymentsComponent {} diff --git a/src/components/common/icons/payments/payments.svg b/src/components/common/icons/payments/payments.svg new file mode 100644 index 0000000..49cb646 --- /dev/null +++ b/src/components/common/icons/payments/payments.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/pencil/pencil.component.ts b/src/components/common/icons/pencil/pencil.component.ts new file mode 100644 index 0000000..1430d3d --- /dev/null +++ b/src/components/common/icons/pencil/pencil.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-pencil', + templateUrl: './pencil.svg', + styleUrls: ['../icons.scss'], +}) +export class IconPencilComponent {} diff --git a/src/components/common/icons/pencil/pencil.svg b/src/components/common/icons/pencil/pencil.svg new file mode 100644 index 0000000..7e190c3 --- /dev/null +++ b/src/components/common/icons/pencil/pencil.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/person/person.component.ts b/src/components/common/icons/person/person.component.ts new file mode 100644 index 0000000..1d1398a --- /dev/null +++ b/src/components/common/icons/person/person.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-person', + templateUrl: './person.svg', + styleUrls: ['../icons.scss'], +}) +export class IconPersonComponent {} diff --git a/src/components/common/icons/person/person.svg b/src/components/common/icons/person/person.svg new file mode 100644 index 0000000..23f87b9 --- /dev/null +++ b/src/components/common/icons/person/person.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/pictures/pictures.component.ts b/src/components/common/icons/pictures/pictures.component.ts new file mode 100644 index 0000000..895bbcb --- /dev/null +++ b/src/components/common/icons/pictures/pictures.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-pictures', + templateUrl: './pictures.svg', + styleUrls: ['../icons.scss'], +}) +export class IconPicturesComponent {} diff --git a/src/components/common/icons/pictures/pictures.svg b/src/components/common/icons/pictures/pictures.svg new file mode 100644 index 0000000..b236ea9 --- /dev/null +++ b/src/components/common/icons/pictures/pictures.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/promo_icon/promo_icon.component.ts b/src/components/common/icons/promo_icon/promo_icon.component.ts new file mode 100644 index 0000000..ee3cfc3 --- /dev/null +++ b/src/components/common/icons/promo_icon/promo_icon.component.ts @@ -0,0 +1,37 @@ +import type { imageURL } from '#types'; + +import { Component, Inject, Input, OnChanges, OnInit } from '@angular/core'; + +import { PromotionService } from '@services/promotion.service'; + +@Component({ + selector: 'sith-icon-promotion', + templateUrl: './promo_icon.html', + styleUrls: ['../icons.scss', './promo_icon.scss'], +}) +export class IconPromotionComponent implements OnInit, OnChanges { + public constructor(@Inject(PromotionService) private readonly promotionService: PromotionService) {} + + @Input() public number?: number; + + public picture?: imageURL; + + public ngOnChanges(): void { + this.setup(); + } + + public ngOnInit(): void { + this.setup(); + } + + public setup() { + if (!this.number) return; + + this.promotionService.promotionPicture(this.number).subscribe({ + next: (data) => { + this.picture = data; + }, + error: (err) => console.error(err), + }); + } +} diff --git a/src/components/common/icons/promo_icon/promo_icon.html b/src/components/common/icons/promo_icon/promo_icon.html new file mode 100644 index 0000000..73e0946 --- /dev/null +++ b/src/components/common/icons/promo_icon/promo_icon.html @@ -0,0 +1,4 @@ + +
+ {{ number }} +
diff --git a/src/components/common/icons/promo_icon/promo_icon.scss b/src/components/common/icons/promo_icon/promo_icon.scss new file mode 100644 index 0000000..edf4fc3 --- /dev/null +++ b/src/components/common/icons/promo_icon/promo_icon.scss @@ -0,0 +1,15 @@ +img, +.placeholder { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.placeholder { + display: flex; + justify-content: center; + align-items: center; + font-family: Roboto, sans-serif; + color: var(--text-color-dynamic); + border: dotted 1.25px var(--text-color-dark-bg); +} diff --git a/src/components/common/icons/search/search.component.ts b/src/components/common/icons/search/search.component.ts new file mode 100644 index 0000000..439df47 --- /dev/null +++ b/src/components/common/icons/search/search.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-search', + templateUrl: './search.svg', + styleUrls: ['../icons.scss'], +}) +export class IconSearchComponent {} diff --git a/src/components/common/icons/search/search.svg b/src/components/common/icons/search/search.svg new file mode 100644 index 0000000..055a513 --- /dev/null +++ b/src/components/common/icons/search/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/shopping_basket/shopping_basket.component.ts b/src/components/common/icons/shopping_basket/shopping_basket.component.ts new file mode 100644 index 0000000..d9e15dd --- /dev/null +++ b/src/components/common/icons/shopping_basket/shopping_basket.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-shopping-basket', + templateUrl: './shopping_basket.svg', + styleUrls: ['../icons.scss'], +}) +export class IconShoppingBasketComponent {} diff --git a/src/components/common/icons/shopping_basket/shopping_basket.svg b/src/components/common/icons/shopping_basket/shopping_basket.svg new file mode 100644 index 0000000..9cebe22 --- /dev/null +++ b/src/components/common/icons/shopping_basket/shopping_basket.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/shopping_cart/shopping_cart.component.ts b/src/components/common/icons/shopping_cart/shopping_cart.component.ts new file mode 100644 index 0000000..c2fbd5a --- /dev/null +++ b/src/components/common/icons/shopping_cart/shopping_cart.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-shopping-cart', + templateUrl: './shopping_cart.svg', + styleUrls: ['../icons.scss'], +}) +export class IconShoppingCartComponent {} diff --git a/src/components/common/icons/shopping_cart/shopping_cart.svg b/src/components/common/icons/shopping_cart/shopping_cart.svg new file mode 100644 index 0000000..e4a220b --- /dev/null +++ b/src/components/common/icons/shopping_cart/shopping_cart.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/icons/upload/upload.component.ts b/src/components/common/icons/upload/upload.component.ts new file mode 100644 index 0000000..fbb8fad --- /dev/null +++ b/src/components/common/icons/upload/upload.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sith-icon-upload', + templateUrl: './upload.svg', + styleUrls: ['../icons.scss'], +}) +export class IconUploadComponent {} diff --git a/src/components/common/icons/upload/upload.svg b/src/components/common/icons/upload/upload.svg new file mode 100644 index 0000000..bc18eb2 --- /dev/null +++ b/src/components/common/icons/upload/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/icons/user_icon/user_icon.component.spec.ts b/src/components/common/icons/user_icon/user_icon.component.spec.ts new file mode 100644 index 0000000..3790d10 --- /dev/null +++ b/src/components/common/icons/user_icon/user_icon.component.spec.ts @@ -0,0 +1,59 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { IconUserComponent } from './user_icon.component'; + +describe('IconUserComponent', () => { + let component: IconUserComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [IconUserComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(IconUserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('hasPicture', () => { + it('should return true if url is defined', () => { + component.url = 'https://example.com/image.jpg'; + expect(component.hasPicture()).toBeTrue(); + }); + + it('should return false if url is undefined', () => { + component.url = undefined; + expect(component.hasPicture()).toBeFalse(); + }); + }); + + describe('notifications', () => { + it('should show notification count if notifications are between 0 and 9', () => { + component.notifications = 5; + fixture.detectChanges(); + const notificationElement = (fixture.nativeElement as HTMLDivElement).querySelector('.notification'); + expect(notificationElement?.textContent).toContain('5'); + }); + + it('should show a circle if notifications are 10 or more', () => { + component.notifications = 10; + fixture.detectChanges(); + const notificationElement = (fixture.nativeElement as HTMLDivElement).querySelector('.notification'); + expect(notificationElement?.querySelector('span')).toBeTruthy(); + }); + + it('should not show any notification if notifications are 0', () => { + component.notifications = 0; + fixture.detectChanges(); + const notificationElement = (fixture.nativeElement as HTMLDivElement).querySelector('.notification'); + expect(notificationElement).toBeFalsy(); + }); + }); +}); diff --git a/src/components/common/icons/user_icon/user_icon.component.ts b/src/components/common/icons/user_icon/user_icon.component.ts new file mode 100644 index 0000000..f02bcb5 --- /dev/null +++ b/src/components/common/icons/user_icon/user_icon.component.ts @@ -0,0 +1,15 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'sith-icon-user', + templateUrl: './user_icon.html', + styleUrls: ['../icons.scss', './user_icon.scss'], +}) +export class IconUserComponent { + @Input() public url?: string; + @Input() public notifications? = 0; + + public hasPicture(): boolean { + return this.url !== undefined && this.url !== null; + } +} diff --git a/src/components/common/icons/user_icon/user_icon.html b/src/components/common/icons/user_icon/user_icon.html new file mode 100644 index 0000000..309219f --- /dev/null +++ b/src/components/common/icons/user_icon/user_icon.html @@ -0,0 +1,15 @@ +
+
+ user_profile_picture +
+
+ + + + + +
+ +
{{ notifications }}
+
+
diff --git a/src/components/common/icons/user_icon/user_icon.scss b/src/components/common/icons/user_icon/user_icon.scss new file mode 100644 index 0000000..c99fe57 --- /dev/null +++ b/src/components/common/icons/user_icon/user_icon.scss @@ -0,0 +1,53 @@ +.icon { + position: relative; + width: 100%; + height: 100%; + + > .image { + position: absolute; + overflow: hidden; + width: 100%; + height: 100%; + + > svg, + > img { + width: 100%; + height: 100%; + border-radius: 50%; + } + + > svg { + .light { + fill: var(--navbar-user-icon-light-color); + } + + .dark { + fill: var(--navbar-user-icon-dark-color); + } + } + } + + > .notification { + position: absolute; + top: -4px; + right: -4px; + min-width: 16px; + height: 16px; + color: var(--text-color-dark-bg); + background-color: var(--red); + border-radius: 50%; + font-family: Roboto, sans-serif; + font-size: calc(12px * var(--font-size)); + display: flex; + align-items: center; + justify-content: center; + + > span { + display: block; + background-color: var(--text-color-dark-bg); + width: 100%; + height: 100%; + border-radius: 50%; + } + } +} diff --git a/src/components/common/image_cropper/image-cropper.component.spec.ts b/src/components/common/image_cropper/image-cropper.component.spec.ts new file mode 100644 index 0000000..e722904 --- /dev/null +++ b/src/components/common/image_cropper/image-cropper.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImageCropperComponent } from './image-cropper.component'; + +describe('ImageCropperComponent', () => { + let component: ImageCropperComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ImageCropperComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ImageCropperComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/components/common/image_cropper/image-cropper.component.ts b/src/components/common/image_cropper/image-cropper.component.ts new file mode 100644 index 0000000..a6c46bb --- /dev/null +++ b/src/components/common/image_cropper/image-cropper.component.ts @@ -0,0 +1,125 @@ +import type { base64 } from '#types'; +import type { ImageCropperResult, ImageCropperSetting } from 'types'; + +import { + Component, + OnDestroy, + ViewEncapsulation, + ElementRef, + ViewChild, + Input, + EventEmitter, + Output, +} from '@angular/core'; +import Cropper from 'cropperjs'; + +@Component({ + selector: 'sith-image-cropper', + templateUrl: './image-cropper.html', + styleUrls: ['./image-cropper.scss'], + encapsulation: ViewEncapsulation.None, +}) +export class ImageCropperComponent implements OnDestroy { + @ViewChild('image') public image!: ElementRef; + + @Input() public imageUrl?: string; + @Input() public settings?: ImageCropperSetting; + @Input() public cropbox?: Cropper.CropBoxData; + @Input() public loadImageErrorText?: string; + @Input() public cropperOptions?: Cropper.Options = {}; + + @Output() public export = new EventEmitter(); + @Output() public ready = new EventEmitter(); + + public isLoading = true; + public cropper?: Cropper; + public imageElement?: HTMLImageElement; + public loadError?: boolean = false; + + public ngOnDestroy() { + if (this.cropper) { + this.cropper.destroy(); + this.cropper = undefined; + } + } + + public imageLoaded(ev: Event) { + this.loadError = false; + + // Setup image element + const image = ev.target as HTMLImageElement; + this.imageElement = image; + + // Add crossOrigin? + if (this.cropperOptions?.checkCrossOrigin) image.crossOrigin = 'anonymous'; + + // Image on ready event + image.addEventListener('ready', () => { + // Emit ready + this.ready.emit(true); + + // Unset loading state + this.isLoading = false; + + // Validate cropbox existence + if (this.cropbox && this.cropper) this.cropper.setCropBoxData(this.cropbox); + }); + + // Setup aspect ratio according to settings + let aspectRatio = NaN; + if (this.settings) { + const { width, height } = this.settings; + aspectRatio = width / height; + } + + // Set crop options + // extend default with custom config + this.cropperOptions = Object.merge( + { + aspectRatio, + movable: false, + scalable: false, + zoomable: false, + viewMode: 1, + checkCrossOrigin: true, + }, + { + ...this.cropperOptions, + }, + ); + + // Set cropperjs + if (this.cropper) { + this.cropper.destroy(); + this.cropper = undefined; + } + + this.cropper = new Cropper(image, this.cropperOptions); + } + + public imageLoadError() { + this.loadError = true; + this.isLoading = false; + } + + public async exportCanvas() { + if (!this.cropper) return; + + // Get and set image, crop and canvas data + const imageData = this.cropper.getImageData(); + const cropData = this.cropper.getCropBoxData(); + const canvas = this.cropper.getCroppedCanvas(); + const data = { imageData, cropData }; + + // Create promise to resolve canvas data + const promise = new Promise>((resolve) => { + // Validate base64 and resolve promise with dataUrl + return resolve({ dataUrl: canvas.toDataURL('image/png') as base64 }); + }); + + // Emit export data when promise is ready + await promise.then((res) => { + this.export.emit(Object.merge(data, res)); + }); + } +} diff --git a/src/components/common/image_cropper/image-cropper.html b/src/components/common/image_cropper/image-cropper.html new file mode 100644 index 0000000..45f6f78 --- /dev/null +++ b/src/components/common/image_cropper/image-cropper.html @@ -0,0 +1,15 @@ +
+ + +
+
+
+ + +
{{ loadImageErrorText }}
+ + +
+ image +
+
\ No newline at end of file diff --git a/src/components/common/image_cropper/image-cropper.scss b/src/components/common/image_cropper/image-cropper.scss new file mode 100644 index 0000000..5728038 --- /dev/null +++ b/src/components/common/image_cropper/image-cropper.scss @@ -0,0 +1,335 @@ +:host { + display: block; +} + +.cropper { + overflow: hidden; + + img { + max-width: 100%; + max-height: 100%; + height: auto; + } +} + +.cropper-wrapper { + position: relative; + min-height: 80px; + + .loading-block { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + + .spinner { + width: 31px; + height: 31px; + margin: 0 auto; + border: 2px solid rgba(97, 100, 193, .98); + border-radius: 50%; + border-left-color: transparent; + border-right-color: transparent; + -webkit-animation: cssload-spin 425ms infinite linear; + position: absolute; + top: calc(50% - 15px); + left: calc(50% - 15px); + animation: cssload-spin 425ms infinite linear; + } + } +} + +@-webkit-keyframes cssload-spin { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +@keyframes cssload-spin { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +/*! + * Cropper.js v1.4.1 + * https://fengyuanchen.github.io/cropperjs + * + * Copyright 2015-present Chen Fengyuan + * Released under the MIT license + * + * Date: 2018-07-15T09:54:43.167Z + */ + +.cropper-container { + direction: ltr; + font-size: 0; + line-height: 0; + position: relative; + -ms-touch-action: none; + touch-action: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + img { + display: block; + height: 100%; + image-orientation: 0deg; + max-height: none !important; + max-width: none !important; + min-height: 0 !important; + min-width: 0 !important; + width: 100%; + } +} + +.cropper-wrap-box, +.cropper-canvas, +.cropper-drag-box, +.cropper-crop-box, +.cropper-modal { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; +} + +.cropper-wrap-box, +.cropper-canvas { + overflow: hidden; +} + +.cropper-drag-box { + background-color: #fff; + opacity: 0; +} + +.cropper-modal { + background-color: #000; + opacity: .5; +} + +.cropper-view-box { + display: block; + height: 100%; + outline-color: rgba(51, 153, 255, 0.75); + outline: 1px solid #39f; + overflow: hidden; + width: 100%; +} + +.cropper-dashed { + border: 0 dashed #eee; + display: block; + opacity: .5; + position: absolute; + + &.dashed-h { + border-bottom-width: 1px; + border-top-width: 1px; + height: calc(100% / 3); + left: 0; + top: calc(100% / 3); + width: 100%; + } + + &.dashed-v { + border-left-width: 1px; + border-right-width: 1px; + height: 100%; + left: calc(100% / 3); + top: 0; + width: calc(100% / 3); + } +} + +.cropper-center { + display: block; + height: 0; + left: 50%; + opacity: .75; + position: absolute; + top: 50%; + width: 0; + + &:before, + &:after { + background-color: #eee; + content: ' '; + display: block; + position: absolute; + } + + &:before { + height: 1px; + left: -3px; + top: 0; + width: 7px; + } + + &:after { + height: 7px; + left: 0; + top: -3px; + width: 1px; + } +} + +.cropper-face, +.cropper-line, +.cropper-point { + display: block; + height: 100%; + opacity: .1; + position: absolute; + width: 100%; +} + +.cropper-face { + background-color: var(--background-color); + left: 0; + top: 0; +} + +.cropper-line { + background-color: var(--dark-blue); + + &.line-e { + cursor: ew-resize; + right: -3px; + top: 0; + width: 5px; + } + + &.line-n { + cursor: ns-resize; + height: 5px; + left: 0; + top: -3px; + } + + &.line-w { + cursor: ew-resize; + left: -3px; + top: 0; + width: 5px; + } + + &.cropper-line.line-s { + bottom: -3px; + cursor: ns-resize; + height: 5px; + left: 0; + } +} + +.cropper-point { + background-color: var(--dark-blue); + height: 5px; + opacity: .75; + width: 5px; + + &.point-e { + cursor: ew-resize; + margin-top: -3px; + right: -3px; + top: 50%; + } + + &.point-n { + cursor: ns-resize; + left: 50%; + margin-left: -3px; + top: -3px; + } + + &.point-w { + cursor: ew-resize; + left: -3px; + margin-top: -3px; + top: 50%; + } + + &.point-s { + bottom: -3px; + cursor: s-resize; + left: 50%; + margin-left: -3px; + } + + &.point-ne { + cursor: nesw-resize; + right: -3px; + top: -3px; + } + + &.point-nw { + cursor: nwse-resize; + left: -3px; + top: -3px; + } + + &.point-sw { + bottom: -3px; + cursor: nesw-resize; + left: -3px; + } + + &.point-se { + bottom: -3px; + cursor: nwse-resize; + opacity: 1; + right: -3px; + + &:before { + background-color: var(--dark-blue); + bottom: -50%; + content: ' '; + display: block; + height: 200%; + opacity: 0; + position: absolute; + right: -50%; + width: 200%; + } + } +} + +.cropper-invisible { + opacity: 0; +} + +.cropper-hide { + display: block; + height: 0; + position: absolute; + width: 0; +} + +.cropper-hidden { + display: none !important; +} + +.cropper-move { + cursor: move; +} + +.cropper-crop { + cursor: crosshair; +} + +.cropper-disabled { + + .cropper-drag-box, + .cropper-face, + .cropper-line, + .cropper-point { + cursor: not-allowed; + } +} \ No newline at end of file diff --git a/src/components/common/inputs/file_input/file-input.component.ts b/src/components/common/inputs/file_input/file-input.component.ts new file mode 100644 index 0000000..f8b09ed --- /dev/null +++ b/src/components/common/inputs/file_input/file-input.component.ts @@ -0,0 +1,30 @@ +import type { base64 } from '#types'; + +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'sith-file-input', + templateUrl: './file-input.html', + styleUrls: ['./file-input.scss'], +}) +export class FileInputComponent { + public filename = ''; + + @Input() public inputAccept = 'image/*'; + @Output() public fileChange: EventEmitter = new EventEmitter(); + + public onFileChange(event: Event): void { + const input = event.target as HTMLInputElement; + + if (input && input.files && input.files[0]) { + const reader = new FileReader(); + + reader.onload = (event: ProgressEvent) => { + this.fileChange.emit((event.target).result as base64); + }; + + reader.readAsDataURL(input.files[0]); + this.filename = input.files[0].name; + } + } +} diff --git a/src/components/common/inputs/file_input/file-input.html b/src/components/common/inputs/file_input/file-input.html new file mode 100644 index 0000000..895ea1b --- /dev/null +++ b/src/components/common/inputs/file_input/file-input.html @@ -0,0 +1,12 @@ +
+
+ + {{ filename }} +
+ + +
diff --git a/src/components/common/inputs/file_input/file-input.scss b/src/components/common/inputs/file_input/file-input.scss new file mode 100644 index 0000000..b59c291 --- /dev/null +++ b/src/components/common/inputs/file_input/file-input.scss @@ -0,0 +1,53 @@ +.container { + position: relative; + height: 32px; + + > .fake-input-file { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + + z-index: 0; + + display: flex; + gap: 5px; + align-items: center; + justify-content: center; + + > .label { + width: 100%; + height: 32px; + background-color: var(--gray1-hover); + border-radius: 5px; + + padding-left: 10px; + display: flex; + align-items: center; + + font-family: 'Roboto', sans-serif; + font-size: 14px; + color: var(--text-color-dynamic); + } + + > .icon { + width: 32px; + height: 32px; + padding: 4px; + fill: var(--text-color-dynamic); + } + } + + > input { + position: absolute; + top: 0; + left: 0; + opacity: 0; + cursor: pointer; + width: 100%; + height: 100%; + + z-index: 1; + } +} diff --git a/src/components/common/inputs/password_input/pass-input.component.ts b/src/components/common/inputs/password_input/pass-input.component.ts new file mode 100644 index 0000000..88ecf45 --- /dev/null +++ b/src/components/common/inputs/password_input/pass-input.component.ts @@ -0,0 +1,47 @@ +import { Component, Input, forwardRef } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; + +@Component({ + selector: 'sith-password-input', + templateUrl: './pass-input.html', + styleUrls: ['./pass-input.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => PasswordInputComponent), + multi: true, + }, + ], +}) +export class PasswordInputComponent implements ControlValueAccessor { + @Input() public autocomplete: 'on' | 'off' | 'current-password' | 'new-password' = 'off'; + + public type: 'password' | 'text' = 'password'; + + public toggleVisibility() { + this.type = this.type === 'password' ? 'text' : 'password'; + } + + // weird type because of 'any' type in ControlValueAccessor methods + // -> tell me you're using 'any' without telling me you're using 'any' + public onChange!: Parameters[0]; + public onTouch!: Parameters[0]; + + public input: unknown; + + registerOnChange(fn: Parameters[0]): void { + this.onChange = fn as unknown; + } + registerOnTouched(fn: Parameters[0]): void { + this.onTouch = fn as unknown; + } + + writeValue(obj: Parameters[0]): void { + this.input = obj; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setDisabledState?(isDisabled: boolean): void { + return; + } +} diff --git a/src/components/common/inputs/password_input/pass-input.html b/src/components/common/inputs/password_input/pass-input.html new file mode 100644 index 0000000..200779d --- /dev/null +++ b/src/components/common/inputs/password_input/pass-input.html @@ -0,0 +1,8 @@ +
+ + +
diff --git a/src/components/common/inputs/password_input/pass-input.scss b/src/components/common/inputs/password_input/pass-input.scss new file mode 100644 index 0000000..41d7fb0 --- /dev/null +++ b/src/components/common/inputs/password_input/pass-input.scss @@ -0,0 +1,46 @@ +$icon-size: 20px; +$input-height: 32px; + +div { + position: relative; + + > .icon { + opacity: 0; + right: 5px; + top: calc(($input-height - $icon-size) / 2); + fill: var(--text-color-dark-bg); + position: absolute; + height: $icon-size; + width: $icon-size; + + &:focus, + &:hover { + cursor: pointer; + opacity: 1; + } + } + + > input { + font-family: Roboto, sans-serif; + font-weight: normal; + color: var(--text-color-dark-bg); + background-color: var(--gray4); + width: 100%; + border: none; + border-radius: 5px; + height: $input-height; + padding: 5px 5px 5px 10px; + display: flex; + justify-content: flex-start; + align-items: center; + + &::placeholder { + color: var(--text-color-dark-bg-placeholder); + font-size: calc(14px * var(--font-size)); + } + + &:hover ~ .icon, &:focus ~ .icon { + opacity: 1; + } + } +} diff --git a/src/components/common/selectors/font_size/font_size_selector.component.ts b/src/components/common/selectors/font_size/font_size_selector.component.ts new file mode 100644 index 0000000..2b68dbb --- /dev/null +++ b/src/components/common/selectors/font_size/font_size_selector.component.ts @@ -0,0 +1,28 @@ +import type { FontSize } from 'types'; + +import { Component, Inject } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-font-size-selector', + templateUrl: './font_size_selector.html', + styleUrls: ['./font_size_selector.scss'], +}) +export class FontSizeSelectorComponent { + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(TranslateService) public readonly t: TranslateService, + ) { + this.sizes.forEach((size) => { + t.get(size.label).subscribe((label: string) => (size.label = label)); + }); + } + + public readonly sizes: Array<{ class: string; label: string; value: FontSize }> = [ + { class: 'small', label: 'header.options.font_size.small', value: '0.75' }, + { class: 'medium', label: 'header.options.font_size.medium', value: '1' }, + { class: 'large', label: 'header.options.font_size.large', value: '1.25' }, + ]; +} diff --git a/src/components/common/selectors/font_size/font_size_selector.html b/src/components/common/selectors/font_size/font_size_selector.html new file mode 100644 index 0000000..5bcf099 --- /dev/null +++ b/src/components/common/selectors/font_size/font_size_selector.html @@ -0,0 +1,5 @@ + +
+ +
diff --git a/src/components/common/selectors/font_size/font_size_selector.scss b/src/components/common/selectors/font_size/font_size_selector.scss new file mode 100644 index 0000000..4e02afd --- /dev/null +++ b/src/components/common/selectors/font_size/font_size_selector.scss @@ -0,0 +1,26 @@ +.buttons { + display: flex; + justify-content: space-between; + margin-top: 10px; + gap: 10px; + + > * ::ng-deep button { + border: 1px solid transparent; + } + + >.active ::ng-deep button { + border: 1px solid var(--gray2); + } + + >.small ::ng-deep button { + font-size: calc(12px * .75); + } + + >.medium ::ng-deep button { + font-size: 12px; + } + + >.large ::ng-deep button { + font-size: calc(12px * 1.25); + } +} diff --git a/src/components/common/selectors/lang/lang_selector.component.spec.ts b/src/components/common/selectors/lang/lang_selector.component.spec.ts new file mode 100644 index 0000000..daaff5b --- /dev/null +++ b/src/components/common/selectors/lang/lang_selector.component.spec.ts @@ -0,0 +1,39 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { LangSelectorComponent } from './lang_selector.component'; +import { CommonComponentsModule } from '../../common.module'; + +describe('MobileLangSelectorComponent', () => { + let component: LangSelectorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LangSelectorComponent], + imports: [TranslateModule.forRoot(), CommonComponentsModule], + providers: [PageService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LangSelectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should return the default language when no language is set', () => { + spyOnProperty(component.p, 'lang', 'get').and.returnValue('anything'); + expect(component.selection).toEqual({ + label: 'English', + value: 'en-US', + image: 'assets/flags/en-GB.svg', + }); + }); +}); diff --git a/src/components/common/selectors/lang/lang_selector.component.ts b/src/components/common/selectors/lang/lang_selector.component.ts new file mode 100644 index 0000000..ec7edd0 --- /dev/null +++ b/src/components/common/selectors/lang/lang_selector.component.ts @@ -0,0 +1,54 @@ +import type { SelectComponentOption } from 'types'; + +import { Component, Inject, OnInit } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; + +import { PageService } from '@services/page.service'; +import { getLanguageCompletion, LANGUAGES } from '@utils/i18n'; + +@Component({ + selector: 'sith-lang-selector', + templateUrl: './lang_selector.html', + styleUrls: ['./lang_selector.scss'], +}) +export class LangSelectorComponent implements OnInit { + public langs: SelectComponentOption[] = LANGUAGES.map((lang) => ({ + value: lang.filename, + label: lang.label, + image: lang.image, + })); + + public langsCompletion: Array<[string, Observable]> = this.langs.map((lang) => [ + lang.label, + getLanguageCompletion(lang.value), + ]); + + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(TranslateService) public readonly t: TranslateService, + ) {} + + public ngOnInit(): void { + this.langsCompletion.forEach(([lang, completion$]) => { + completion$.subscribe((completion) => { + const found: SelectComponentOption | undefined = this.langs.find((l) => l.label === lang); + if (found) found.label = `${lang} (${completion}%)`; + }); + }); + } + + public get selection(): SelectComponentOption { + return ( + LANGUAGES.map((lang) => ({ + label: lang.label, + value: lang.filename, + image: lang.image, + })).find((lang) => lang.value === this.page.lang) ?? { + label: 'English', + value: 'en-US', + image: 'assets/flags/en-GB.svg', + } + ); + } +} diff --git a/src/components/common/selectors/lang/lang_selector.html b/src/components/common/selectors/lang/lang_selector.html new file mode 100644 index 0000000..9aecfb3 --- /dev/null +++ b/src/components/common/selectors/lang/lang_selector.html @@ -0,0 +1,7 @@ + diff --git a/src/components/common/selectors/lang/lang_selector.scss b/src/components/common/selectors/lang/lang_selector.scss new file mode 100644 index 0000000..00831ee --- /dev/null +++ b/src/components/common/selectors/lang/lang_selector.scss @@ -0,0 +1,34 @@ +$link-color: #0d80c8; + +.selector { + width: 100%; + height: 75px; + display: flex; + flex-direction: column; + gap: 10px; + + > div { + display: flex; + flex-direction: column; + gap: 2px; + + .link { + width: fit-content; + margin: 0 auto; + color: $link-color; + height: 16px; + text-decoration: none; + font-family: Inter, sans-serif; + font-size: 10px; + font-style: italic; + font-weight: 400; + line-height: 12px; + text-align: center; + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + } +} diff --git a/src/components/common/selectors/select/select.component.spec.ts b/src/components/common/selectors/select/select.component.spec.ts new file mode 100644 index 0000000..c0f915c --- /dev/null +++ b/src/components/common/selectors/select/select.component.spec.ts @@ -0,0 +1,121 @@ +import type { SelectComponentOption } from 'types'; + +import { DebugElement } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { TranslateModule } from '@ngx-translate/core'; + +import { SelectComponent } from './select.component'; +import { IconsModule } from '../../icons/icons.module'; + +describe('SelectComponent', () => { + let component: SelectComponent; + let fixture: ComponentFixture; + let button: DebugElement; + let dropdown: DebugElement; + + const unsortedOptions: SelectComponentOption[] = [ + { label: 'Option 1', value: '1' }, + { label: 'Option 3', value: '3' }, + { label: 'Option 2', value: '2' }, + ]; + + const sortedOptions: SelectComponentOption[] = [ + { label: 'Option 1', value: '1' }, + { label: 'Option 2', value: '2' }, + { label: 'Option 3', value: '3' }, + ]; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SelectComponent], + imports: [IconsModule, TranslateModule.forRoot()], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SelectComponent); + component = fixture.componentInstance; + component.options = unsortedOptions; + fixture.detectChanges(); + + button = fixture.debugElement.query(By.css('.selector')); + dropdown = fixture.debugElement.query(By.css('.dropdown')); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should toggle dropdown visibility on button click', () => { + expect(component.dropdownVisible).toBeFalse(); + + (button.nativeElement as HTMLButtonElement).click(); + fixture.detectChanges(); + expect(component.dropdownVisible).toBeTrue(); + + (button.nativeElement as HTMLButtonElement).click(); + fixture.detectChanges(); + expect(component.dropdownVisible).toBeFalse(); + }); + + it('should sort options by label', () => { + expect(component.sortOptions()).toEqual(sortedOptions); + }); + + it('should select option and emit value', () => { + const selectedOption = sortedOptions[1]; + const dropdownVisible = component.dropdownVisible; + spyOn(component.optionSelected, 'emit'); + expect(component.selectedOption).toEqual(component.DEFAULT_OPTION); + + component.selectOption(selectedOption); + expect(component.selectedOption).toEqual(selectedOption); + expect(component.optionSelected.emit).toHaveBeenCalledWith(selectedOption.value); + expect(component.dropdownVisible).toEqual(!dropdownVisible); + }); + + it('should display selected option label and image', () => { + const selectedOption = sortedOptions[1]; + const selectedOptionWithImage = { ...selectedOption, image: 'assets/flags/en-GB.svg' }; + + component.selectedOption = selectedOption; + fixture.detectChanges(); + + const label = fixture.debugElement.query(By.css('.label')); + let image = fixture.debugElement.query(By.css('.image')); + + expect((label.nativeElement as HTMLLabelElement).textContent).toEqual(selectedOption.label); + expect(image).toBeNull(); + + component.selectedOption = selectedOptionWithImage; + fixture.detectChanges(); + image = fixture.debugElement.query(By.css('.image')); + + expect((label.nativeElement as HTMLLabelElement).textContent).toEqual(selectedOptionWithImage.label); + expect((image.nativeElement as HTMLImageElement).getAttribute('src')).toEqual(selectedOptionWithImage.image); + }); + + it('should display dropdown options and select option on click', () => { + const selectedOption = sortedOptions[1]; + spyOn(component, 'selectOption'); + expect(component.dropdownVisible).toBeFalse(); + expect(dropdown).toBeNull(); + + (button.nativeElement as HTMLButtonElement).click(); + fixture.detectChanges(); + + dropdown = fixture.debugElement.query(By.css('.dropdown')); + const optionsElements = fixture.debugElement.queryAll(By.css('.item')); + + expect(dropdown).not.toBeNull(); + expect(component.dropdownVisible).toBeTrue(); + expect(optionsElements.length).toEqual(sortedOptions.length); + + (optionsElements[1].nativeElement as HTMLLIElement).click(); + fixture.detectChanges(); + dropdown = fixture.debugElement.query(By.css('.dropdown')); + + expect(component.selectOption).toHaveBeenCalledWith(selectedOption); + }); +}); diff --git a/src/components/common/selectors/select/select.component.ts b/src/components/common/selectors/select/select.component.ts new file mode 100644 index 0000000..7b0510a --- /dev/null +++ b/src/components/common/selectors/select/select.component.ts @@ -0,0 +1,53 @@ +import type { SelectComponentOption } from 'types'; + +import { Component, EventEmitter, Inject, Input, Output } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-select', + templateUrl: './select.html', + styleUrls: ['./select.scss'], +}) +export class SelectComponent { + public readonly DEFAULT_OPTION: SelectComponentOption = { + label: '', + value: '', + }; + + public dropdownVisible = false; + + /** Options to display in the dropdown */ + @Input() public options: SelectComponentOption[] = []; + /** The currently selected option */ + @Input() public selectedOption: SelectComponentOption = this.DEFAULT_OPTION; + /** Emit an event with a string being the `value` of the selected option */ + @Output() public optionSelected = new EventEmitter(); + + public constructor(@Inject(PageService) public readonly page: PageService) {} + + /** + * Displays or hides the dropdown. + */ + public toggleDropdown() { + this.dropdownVisible = !this.dropdownVisible; + } + + /** + * Sort the options by their label. + * @returns {SelectComponentOption[]} the sorted options + */ + public sortOptions(): SelectComponentOption[] { + return this.options.sort((a, b) => a.label.localeCompare(b.label)); + } + + /** + * Selects an option and emits the value of the option. + * @param {SelectComponentOption} option the option to select + */ + public selectOption(option: SelectComponentOption) { + this.selectedOption = option; + this.optionSelected.emit(option.value); + this.toggleDropdown(); + } +} diff --git a/src/components/common/selectors/select/select.html b/src/components/common/selectors/select/select.html new file mode 100644 index 0000000..8709740 --- /dev/null +++ b/src/components/common/selectors/select/select.html @@ -0,0 +1,27 @@ +
+ + +
diff --git a/src/components/common/selectors/select/select.scss b/src/components/common/selectors/select/select.scss new file mode 100644 index 0000000..5d26daa --- /dev/null +++ b/src/components/common/selectors/select/select.scss @@ -0,0 +1,109 @@ +$height: 26px; +$border-radius: 5px; +$icon-size: 20px; +$padding: 5px; + +.select { + width: 100%; + height: $height; + position: relative; + + > .selector { + cursor: pointer; + position: relative; + background-color: var(--gray4); + border: 0; + border-radius: $border-radius; + display: flex; + flex-direction: row; + height: $height; + width: 100%; + align-items: center; + justify-content: space-between; + padding: $padding; + + &.active { + border-radius: $border-radius $border-radius 0 0; + } + + > .content { + height: 100%; + display: flex; + flex-direction: row; + gap: $padding; + align-items: center; + + > .image { + width: 16px; + height: 16px; + border-radius: 50%; + } + + > .label { + font-family: Inter, sans-serif; + font-size: 12px; + color: var(--text-color-dark-bg); + } + } + + > .icon { + position: absolute; + display: block; + fill: var(--text-color-dark-bg); + height: $icon-size; + width: $icon-size; + right: calc(($height - $icon-size) / 2); + top: calc(($height - $icon-size) / 2); + + &.rtl { + right: unset; + left: calc(($height - $icon-size) / 2); + } + } + } + + > .dropdown { + position: absolute; + top: $height; + background-color: var(--gray4); + width: 100%; + margin: 0; + padding: 0; + border-top: 1px solid var(--user-custom-color); + border-radius: 0 0 $border-radius $border-radius; + max-height: 200px; + overflow-y: scroll; + + > .item { + cursor: pointer; + list-style-type: none; + height: $height; + padding: $padding; + display: flex; + flex-direction: row; + gap: $padding; + align-items: center; + + &:hover { + background-color: var(--gray2); + color: var(--text-color-dynamic); + + &:last-of-type { + border-radius: 0 0 $border-radius $border-radius; + } + } + + > .image { + width: 16px; + height: 16px; + object-fit: contain; + } + + > .label { + font-family: Inter, sans-serif; + font-size: 12px; + color: var(--text-color-dark-bg); + } + } + } +} diff --git a/src/components/common/selectors/theme/theme_selector.component.spec.ts b/src/components/common/selectors/theme/theme_selector.component.spec.ts new file mode 100644 index 0000000..951e6c5 --- /dev/null +++ b/src/components/common/selectors/theme/theme_selector.component.spec.ts @@ -0,0 +1,56 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { ThemeSelectorComponent } from './theme_selector.component'; +import { CommonComponentsModule } from '../../common.module'; + +describe('ThemeSelectorComponent', () => { + let component: ThemeSelectorComponent; + let fixture: ComponentFixture; + let localStore: Record; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ThemeSelectorComponent], + imports: [TranslateModule.forRoot(), CommonComponentsModule], + providers: [PageService, TranslateService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ThemeSelectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + beforeEach(() => { + localStore = {}; + + spyOn(window.localStorage, 'getItem').and.callFake((key: string) => (key in localStore ? localStore[key] : null)); + spyOn(window.localStorage, 'setItem').and.callFake((key: string, value: string) => (localStore[key] = value)); + spyOn(window.localStorage, 'removeItem').and.callFake((key) => delete localStore[key]); + spyOn(window.localStorage, 'clear').and.callFake(() => (localStore = {})); + }); + + afterEach(() => { + localStorage.clear(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should initialize themes and eventThemes', () => { + expect(component.themes.length).toBe(4); + expect(component.themes_event.length).toBeGreaterThanOrEqual(0); + }); + + it('should change page theme on click', () => { + const li = (fixture.nativeElement as HTMLLIElement).querySelector('.themes li') as HTMLLIElement; + li.click(); + expect(component.page.theme).toBe(component.themes[0].value); + }); +}); diff --git a/src/components/common/selectors/theme/theme_selector.component.ts b/src/components/common/selectors/theme/theme_selector.component.ts new file mode 100644 index 0000000..40e4178 --- /dev/null +++ b/src/components/common/selectors/theme/theme_selector.component.ts @@ -0,0 +1,52 @@ +import type { Theme, ThemeEvent } from 'types'; + +import { Component, Inject } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +type ThemeSelector = { + index: number; + name: string; + value: T; +}; + +@Component({ + selector: 'sith-theme-selector', + templateUrl: './theme_selector.html', + styleUrls: ['./theme_selector.scss'], +}) +export class ThemeSelectorComponent { + public themes: ThemeSelector[] = [ + { index: 1, name: 'header.options.themes.auto', value: 'auto' }, + { index: 2, name: 'header.options.themes.light', value: 'light' }, + { index: 3, name: 'header.options.themes.dark', value: 'dark' }, + { index: 4, name: 'header.options.themes.high_contrast', value: 'high_contrast' }, + ]; + + public themes_event: ThemeSelector[] = []; + + public constructor( + @Inject(TranslateService) public readonly t: TranslateService, + @Inject(PageService) public readonly page: PageService, + ) { + switch (new Date().getMonth()) { + case 11: + this.themes_event.push({ index: 1, name: 'header.options.themes_event.christmas', value: 'christmas' }); + break; + case 9: + this.themes_event.push({ index: 1, name: 'header.options.themes_event.pinktober', value: 'pinktober' }); + break; + default: + break; + } + } + + public updateTheme(theme: Theme): void { + this.page.theme = theme; + } + + public updateThemeEvent(theme: ThemeEvent['theme']): void { + this.page.toggleThemeEvent(theme); + } +} diff --git a/src/components/common/selectors/theme/theme_selector.html b/src/components/common/selectors/theme/theme_selector.html new file mode 100644 index 0000000..37a248d --- /dev/null +++ b/src/components/common/selectors/theme/theme_selector.html @@ -0,0 +1,24 @@ + +
    +
  • +
    + {{ theme.name | translate }} +
  • +
+ +
+
    +
  • +
    + {{ theme.name | translate }} +
  • +
+
diff --git a/src/components/common/selectors/theme/theme_selector.scss b/src/components/common/selectors/theme/theme_selector.scss new file mode 100644 index 0000000..a1d785c --- /dev/null +++ b/src/components/common/selectors/theme/theme_selector.scss @@ -0,0 +1,50 @@ +.themes { + padding: 0; + margin: 0; + margin-top: 10px; + display: flex; + flex-direction: column; + + > li { + display: flex; + align-items: center; + gap: 15px; + height: 20px; + cursor: pointer; + + .selector { + background-color: white; + border-radius: 50%; + width: 10px; + height: 10px; + display: flex; + align-items: center; + justify-content: center; + + &.square { + border-radius: 0; + } + } + + &.selected { + > .selector::before { + content: ''; + display: block; + border-radius: 50%; + background-color: var(--gray4); + width: 8px; + height: 8px; + } + + > .selector.square::before { + border-radius: 0; + } + } + + span { + font-family: Inter, sans-serif; + font-size: calc(12px * var(--font-size)); + color: var(--text-color-dark-bg); + } + } +} diff --git a/src/components/common/side_menu/side_disconnected/side_disconnected.component.ts b/src/components/common/side_menu/side_disconnected/side_disconnected.component.ts new file mode 100644 index 0000000..f8abb6d --- /dev/null +++ b/src/components/common/side_menu/side_disconnected/side_disconnected.component.ts @@ -0,0 +1,22 @@ +import { Component, Inject } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +import { SideMenuComponent } from '../side_menu.component'; + +@Component({ + selector: 'sith-side-menu-disconnected', + templateUrl: './side_disconnected.html', + styleUrls: ['./side_disconnected.scss'], +}) +export class SideMenuDisconnectedComponent { + public constructor( + @Inject(PageService) public readonly page: PageService, + private readonly sideMenu: SideMenuComponent, + ) {} + + public to(page: string) { + this.sideMenu.triggerClose(); + this.page.to(page); + } +} diff --git a/src/components/common/side_menu/side_disconnected/side_disconnected.html b/src/components/common/side_menu/side_disconnected/side_disconnected.html new file mode 100644 index 0000000..a30c49e --- /dev/null +++ b/src/components/common/side_menu/side_disconnected/side_disconnected.html @@ -0,0 +1,13 @@ +
+
+ +
+ Association des Étudiants + de l'université de technologie de Belfort-Montbéliard +
+
+
+ + +
+
diff --git a/src/components/common/side_menu/side_disconnected/side_disconnected.scss b/src/components/common/side_menu/side_disconnected/side_disconnected.scss new file mode 100644 index 0000000..ac98036 --- /dev/null +++ b/src/components/common/side_menu/side_disconnected/side_disconnected.scss @@ -0,0 +1,54 @@ +.disconnected-container { + padding: 10px 15px; + display: flex; + flex-direction: column; + gap: 30px; + + >.title { + display: flex; + flex-direction: column; + align-items: center; + + >.logo { + width: 128px; + height: 80px; + display: block; + margin-left: auto; + margin-right: auto; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + } + + >.text-container { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + height: 40px; + + >.text { + color: white; + font-family: Inter, sans-serif; + font-size: calc(23px * var(--font-size)); + white-space: nowrap; + } + + >.small { + font-size: calc(9px * var(--font-size)); + text-transform: uppercase; + } + } + } + + >.buttons { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + + >* { + width: 100%; + } + } +} diff --git a/src/components/common/side_menu/side_menu.component.spec.ts b/src/components/common/side_menu/side_menu.component.spec.ts new file mode 100644 index 0000000..20aeb40 --- /dev/null +++ b/src/components/common/side_menu/side_menu.component.spec.ts @@ -0,0 +1,41 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { SideMenuComponent } from './side_menu.component'; + +describe('SideMenuComponent', () => { + let component: SideMenuComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SideMenuComponent], + imports: [TranslateModule.forRoot()], + providers: [PageService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SideMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + describe('triggerClose', () => { + it('should set closing to true then false after 500ms', (done) => { + component.triggerClose(); + expect(component.closing).toBeTrue(); + + setTimeout(() => { + expect(component.closing).toBeFalse(); + done(); + }, 500); + }); + }); +}); diff --git a/src/components/common/side_menu/side_menu.component.ts b/src/components/common/side_menu/side_menu.component.ts new file mode 100644 index 0000000..de3f773 --- /dev/null +++ b/src/components/common/side_menu/side_menu.component.ts @@ -0,0 +1,28 @@ +import { Component, EventEmitter, Inject, Output } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-side-menu', + templateUrl: './side_menu.html', + styleUrls: ['./side_menu.scss'], +}) +export class SideMenuComponent { + public constructor(@Inject(PageService) public readonly page: PageService) {} + + @Output() public sideMenuClose = new EventEmitter(); + private _closing = false; + + public triggerClose(): void { + this._closing = true; + + setTimeout(() => { + this.sideMenuClose.emit(); + this._closing = false; + }, 500); + } + + public get closing(): boolean { + return this._closing; + } +} diff --git a/src/components/common/side_menu/side_menu.html b/src/components/common/side_menu/side_menu.html new file mode 100644 index 0000000..584514a --- /dev/null +++ b/src/components/common/side_menu/side_menu.html @@ -0,0 +1,6 @@ +
+
+
+ +
+
diff --git a/src/components/common/side_menu/side_menu.scss b/src/components/common/side_menu/side_menu.scss new file mode 100644 index 0000000..92c48ae --- /dev/null +++ b/src/components/common/side_menu/side_menu.scss @@ -0,0 +1,33 @@ +$slide: slide 0.5s ease-in-out; +$slide-rtl: slide-rtl 0.5s ease-in-out; + +.side-menu { + position: fixed; + display: flex; + animation: $slide; + + > .right { + background-color: var(--gray3); + display: block; + width: 316px; + height: 100vh; + + &.closing { + animation: reverse $slide; + } + } + + > .left { + display: block; + width: calc(100vw - 316px); + height: 100vh; + } + + &.rtl { + animation: $slide-rtl; + + > .right.closing { + animation: reverse $slide-rtl; + } + } +} diff --git a/src/components/common/side_menu/side_options/side_options.component.ts b/src/components/common/side_menu/side_options/side_options.component.ts new file mode 100644 index 0000000..3e73478 --- /dev/null +++ b/src/components/common/side_menu/side_options/side_options.component.ts @@ -0,0 +1,12 @@ +import { Component, Inject } from '@angular/core'; + +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-side-menu-options', + templateUrl: './side_options.html', + styleUrls: ['./side_options.scss'], +}) +export class SideMenuOptionsComponent { + public constructor(@Inject(UserService) public readonly u: UserService) {} +} diff --git a/src/components/common/side_menu/side_options/side_options.html b/src/components/common/side_menu/side_options/side_options.html new file mode 100644 index 0000000..f6cce2e --- /dev/null +++ b/src/components/common/side_menu/side_options/side_options.html @@ -0,0 +1,6 @@ +
+ + + + +
diff --git a/src/components/common/side_menu/side_options/side_options.scss b/src/components/common/side_menu/side_options/side_options.scss new file mode 100644 index 0000000..7c38778 --- /dev/null +++ b/src/components/common/side_menu/side_options/side_options.scss @@ -0,0 +1,6 @@ +.options-container { + display: flex; + flex-direction: column; + gap: 20px; + padding: 10px 15px; +} \ No newline at end of file diff --git a/src/components/common/side_menu/side_profile/side_profile.component.spec.ts b/src/components/common/side_menu/side_profile/side_profile.component.spec.ts new file mode 100644 index 0000000..945daf0 --- /dev/null +++ b/src/components/common/side_menu/side_profile/side_profile.component.spec.ts @@ -0,0 +1,43 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +import { SideMenuProfileComponent } from './side_profile.component'; +import { IconsModule } from '../../icons/icons.module'; + +describe('SideMenuProfileComponent', () => { + let component: SideMenuProfileComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SideMenuProfileComponent], + imports: [TranslateModule.forRoot(), IconsModule], + providers: [PageService, UserService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SideMenuProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + describe('logout', () => { + it('should call close.emit and u.logout', () => { + const closeSpy = spyOn(component.sideMenuProfileClose, 'emit'); + const logoutSpy = spyOn(component.user, 'logout'); + + component.logout(); + + expect(closeSpy).toHaveBeenCalled(); + expect(logoutSpy).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/components/common/side_menu/side_profile/side_profile.component.ts b/src/components/common/side_menu/side_profile/side_profile.component.ts new file mode 100644 index 0000000..7759a82 --- /dev/null +++ b/src/components/common/side_menu/side_profile/side_profile.component.ts @@ -0,0 +1,67 @@ +import type { imageURL } from '#types'; +import type { OutputErrorResponseDto, OutputUserDto } from '#types/api'; + +import { Component, Inject } from '@angular/core'; + +import { ApiError } from '@services/api.service'; +import { PageService } from '@services/page.service'; +import { SnackbarService } from '@services/snackbar.service'; +import { UserService } from '@services/user.service'; + +import { SideMenuComponent } from '../side_menu.component'; + +@Component({ + selector: 'sith-side-menu-profile', + templateUrl: './side_profile.html', + styleUrls: ['./side_profile.scss'], +}) +export class SideMenuProfileComponent { + public constructor( + @Inject(UserService) public readonly userService: UserService, + @Inject(PageService) public readonly page: PageService, + @Inject(SnackbarService) public readonly snackbar: SnackbarService, + @Inject(SideMenuComponent) private readonly sideMenu: SideMenuComponent, + ) { + if (this.userService.isLoggedIn()) { + this.userService.user(this.userService.logged_user_id).subscribe({ + next: (user) => (this.user = user), + error: (e: ApiError) => { + console.warn(e); + this.snackbar.error(e.error.message, e.error.errors, e.error.statusCode); + }, + }); + + this.userService.userPicture(this.userService.logged_user_id).subscribe({ + next: (picture) => (this.userPicture = picture), + error: (e: ApiError) => { + console.error(e); + this.snackbar.error(e.error.message, e.error.errors, e.error.statusCode); + }, + }); + + this.userService.userBanner(this.userService.logged_user_id).subscribe({ + next: (banner) => (this.userBanner = banner), + error: (e: ApiError) => { + console.error(e); + this.snackbar.error(e.error.message, e.error.errors, e.error.statusCode); + }, + }); + } + } + + public user?: OutputUserDto; + public userPicture?: imageURL; + public userBanner?: imageURL; + + public logout(): void { + this.sideMenu.triggerClose(); + this.userService.logout().subscribe({ + next: () => this.page.to(['home']), + }); + } + + public to(page: string) { + this.sideMenu.triggerClose(); + this.page.to(['users', `${this.userService.logged_user_id}`, page]); + } +} diff --git a/src/components/common/side_menu/side_profile/side_profile.html b/src/components/common/side_menu/side_profile/side_profile.html new file mode 100644 index 0000000..5d80d4b --- /dev/null +++ b/src/components/common/side_menu/side_profile/side_profile.html @@ -0,0 +1,51 @@ +
+ + + + +
+
+ +
+ {{ user?.full_name }} + 200 € +
+
+
+ +
+
+
+
+ +
+ + + {{ 'header.profile.disconnect' | translate }} +
+
diff --git a/src/components/common/side_menu/side_profile/side_profile.scss b/src/components/common/side_menu/side_profile/side_profile.scss new file mode 100644 index 0000000..7ddebbc --- /dev/null +++ b/src/components/common/side_menu/side_profile/side_profile.scss @@ -0,0 +1,196 @@ +$banner-height: calc(316px / 3); +$no-banner-height: 35px; +$padding: 16px; + +.ae-sticker { + width: 51px; + border-radius: 5px; + display: block; + height: 35px; + border: dotted 1.25px var(--text-color-dark-bg); +} + +.profile-container { + position: relative; + height: 100%; + + >.banner { + + >.background-image { + width: 100%; + height: $banner-height; + background-color: var(--navbar-background-color); + background-size: cover; + background-repeat: no-repeat; + background-position: center; + display: flex; + align-items: flex-end; + justify-content: flex-end; + padding: 5px; + gap: 5px; + + >.promotion { + display: block; + height: 35px; + width: 35px; + border-radius: 50%; + } + } + + >.user-picture { + position: absolute; + width: 100px; + height: 100px; + left: 5px; + top: calc($banner-height - 50px); + + &.rtl { + left: unset; + right: 5px; + } + } + + >.infos { + margin-left: 105px; + color: var(--text-color-dark-bg); + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 5px; + min-height: 50px; + font-family: Roboto, sans-serif; + font-weight: 500; + font-size: calc(14px * var(--font-size)); + + &.rtl { + margin-left: 0; + margin-right: 110px; + } + + >.left { + display: flex; + flex-direction: column; + + > .name { + text-transform: capitalize; + } + } + } + } + + >.no-banner { + padding: $padding $padding 0; + display: flex; + flex-direction: row; + max-height: calc($no-banner-height + $padding); + + >.left { + width: 100%; + display: flex; + flex-direction: row; + gap: 5px; + + >.user-picture { + height: $no-banner-height; + width: $no-banner-height; + } + + >.infos { + color: var(--text-color-dark-bg); + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + padding: 5px; + font-family: Roboto, sans-serif; + font-weight: 500; + font-size: calc(14px * var(--font-size)); + } + } + + >.right { + display: flex; + flex-direction: row; + gap: 5px; + + >.promotion { + display: block; + height: $no-banner-height; + width: $no-banner-height; + border-radius: 50%; + } + } + } + + + // >.background-image.has-banner ~ .user-picture { + // top: calc($banner-height - 50px); + // } + + > main { + padding: $padding $padding calc(2 * $padding); + height: calc(100vh - $no-banner-height - 50px); + display: flex; + flex-direction: column; + justify-content: space-between; + + .links { + display: flex; + background-color: var(--gray4); + height: 30px; + padding: 5px 10px; + align-items: center; + justify-content: space-evenly; + border-radius: 5px; + margin: 0; + + > li { + cursor: pointer; + display: flex; + align-items: center; + gap: 5px; + + + > .icon { + width: 16px; + height: 16px; + fill: var(--text-color-dark-bg); + } + + span { + color: var(--text-color-dark-bg); + font-family: Roboto, sans-serif; + font-weight: 400; + font-size: calc(10px * var(--font-size)); + text-transform: uppercase; + } + + &:hover { + > .icon { + fill: var(--blue); + } + + span { + color: var(--blue); + } + } + } + } + + .logout { + cursor: pointer; + color: var(--red); + font-family: Roboto, sans-serif; + font-weight: normal; + font-size: calc(16px * var(--font-size)); + height: 20px; + text-transform: uppercase; + text-align: center; + width: 100%; + } + } + + >.banner~main { + height: calc(100vh - $banner-height - 50px); + } +} diff --git a/src/components/common/snackbar/snackbar.component.ts b/src/components/common/snackbar/snackbar.component.ts new file mode 100644 index 0000000..887ea09 --- /dev/null +++ b/src/components/common/snackbar/snackbar.component.ts @@ -0,0 +1,39 @@ +import { Component, Inject, OnInit } from '@angular/core'; + +import { SnackbarService } from '@services/snackbar.service'; + +@Component({ + selector: 'sith-snackbar', + templateUrl: './snackbar.html', + styleUrls: ['./snackbar.scss'], +}) +export class SnackbarComponent implements OnInit { + public constructor(@Inject(SnackbarService) private readonly snackbarService: SnackbarService) {} + + public shown = false; + public message = ''; + public type: 'success' | 'error' = 'success'; + public title = ''; + public hiding = false; + + ngOnInit() { + this.snackbarService.registerSnackbarComponent(this); + } + + public show(message: string, title: string, type: 'success' | 'error' = 'success'): void { + this.message = message; + this.type = type; + this.shown = true; + this.title = title; + this.hiding = true; + + setTimeout(() => { + this.hide(); + }, 3000); + } + + public hide() { + this.shown = false; + this.hiding = false; + } +} diff --git a/src/components/common/snackbar/snackbar.html b/src/components/common/snackbar/snackbar.html new file mode 100644 index 0000000..7ffbff5 --- /dev/null +++ b/src/components/common/snackbar/snackbar.html @@ -0,0 +1,10 @@ +
+
+ +
+

{{ title }}

+ {{ message }} +
+
+
+
diff --git a/src/components/common/snackbar/snackbar.scss b/src/components/common/snackbar/snackbar.scss new file mode 100644 index 0000000..ab29805 --- /dev/null +++ b/src/components/common/snackbar/snackbar.scss @@ -0,0 +1,95 @@ +$padding: 10px; + +.snackbar { + bottom: $padding; + right: $padding; + position: absolute; + z-index: 1000; + + min-width: 350px; + max-width: calc(100% - (2 * $padding)); + border-radius: calc($padding / 2); + + font-size: calc(12px * var(--font-size)); + font-family: Inter, sans-serif; + + overflow: hidden; + + &.success { + background-color: var(--green); + } + + &.error { + background-color: var(--red); + } + + > .content { + display: flex; + flex-direction: row; + align-items: center; + padding: $padding; + gap: $padding; + + > .close { + min-width: calc(25px * var(--font-size)); + height: calc(25px * var(--font-size)); + border-radius: 50%; + + &:hover { + cursor: pointer; + background-color: rgba(0, 0, 0, 0.1); + } + } + + > .text { + max-width: calc(100% - 25px * var(--font-size)); + overflow-wrap: break-word; + + > h4 { + margin: 0; + margin-bottom: 5px; + } + } + } + + > .loading { + width: 100%; + height: 8px; + background-color: rgba(0, 0, 0, 0.1); + bottom: 0; + left: 0; + + &.hiding::before { + content: ""; + position: absolute; + width: 20%; + height: 100%; + background-color: rgba(0, 0, 0, 0.3); + animation: snackbar-loading 3s linear infinite; + } + } + + &.hiding { + animation: 500ms snackbar-hiding 2500ms ease-out forwards; + } +} + +@keyframes snackbar-loading { + 0% { + width: 0; + } + + 100% { + width: 100%; + } +} + +@keyframes snackbar-hiding { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} diff --git a/src/components/common/subtitle/subtitle.component.spec.ts b/src/components/common/subtitle/subtitle.component.spec.ts new file mode 100644 index 0000000..97da8bb --- /dev/null +++ b/src/components/common/subtitle/subtitle.component.spec.ts @@ -0,0 +1,51 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { SubtitleComponent } from './subtitle.component'; + +describe('SubtitleComponent', () => { + let component: SubtitleComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SubtitleComponent], + imports: [TranslateModule.forRoot()], + providers: [PageService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SubtitleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should render text', () => { + const text = 'Hello World'; + component.text = text; + fixture.detectChanges(); + const element = (fixture.nativeElement as HTMLTitleElement).querySelector('h2'); + expect(element?.textContent?.trim()).toBe(text); + }); + + it('should add bordered class when bordered input is true', () => { + component.bordered = true; + fixture.detectChanges(); + const element = (fixture.nativeElement as HTMLTitleElement).querySelector('h2'); + expect(element?.classList.contains('bordered')).toBe(true); + }); + + it('should add dark-mode class when onDarkBackground input is true', () => { + component.onDarkBackground = true; + fixture.detectChanges(); + const element = (fixture.nativeElement as HTMLTitleElement).querySelector('h2'); + expect(element?.classList.contains('dark-mode')).toBe(true); + }); +}); diff --git a/src/components/common/subtitle/subtitle.component.ts b/src/components/common/subtitle/subtitle.component.ts new file mode 100644 index 0000000..ce03396 --- /dev/null +++ b/src/components/common/subtitle/subtitle.component.ts @@ -0,0 +1,16 @@ +import { Component, Inject, Input } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-subtitle', + templateUrl: './subtitle.html', + styleUrls: ['./subtitle.scss'], +}) +export class SubtitleComponent { + @Input() public text = ''; + @Input() public bordered = false; + @Input() public onDarkBackground = false; + + public constructor(@Inject(PageService) public readonly page: PageService) {} +} diff --git a/src/components/common/subtitle/subtitle.html b/src/components/common/subtitle/subtitle.html new file mode 100644 index 0000000..c95c42a --- /dev/null +++ b/src/components/common/subtitle/subtitle.html @@ -0,0 +1 @@ +

{{ text }}

diff --git a/src/components/common/subtitle/subtitle.scss b/src/components/common/subtitle/subtitle.scss new file mode 100644 index 0000000..eefa68f --- /dev/null +++ b/src/components/common/subtitle/subtitle.scss @@ -0,0 +1,36 @@ +$text-color: #000; +$dark-mode-text-color: #fff; + +h2 { + font-family: Inter, sans-serif; + font-style: normal; + font-weight: 400; + font-size: calc(12px * var(--font-size)); + line-height: calc(15px * var(--font-size)); + text-transform: uppercase; + margin: 0; +} + +.bordered { + border-left: 4px solid $text-color; + padding-left: 6px; + + &.rtl { + border-left: none !important; + padding-left: 0 !important; + border-right: 4px solid $text-color; + padding-right: 6px; + + &.dark-mode { + border-right: 4px solid $dark-mode-text-color; + } + } + + &.dark-mode { + border-left: 4px solid $dark-mode-text-color; + } +} + +.dark-mode { + color: $dark-mode-text-color; +} diff --git a/src/components/common/title/title.component.ts b/src/components/common/title/title.component.ts new file mode 100644 index 0000000..61639b5 --- /dev/null +++ b/src/components/common/title/title.component.ts @@ -0,0 +1,14 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'sith-title', + templateUrl: './title.html', + styleUrls: ['./title.scss'], +}) +export class TitleComponent { + @Input() public text = ''; + @Input() public onDarkBackground = false; + @Input() public adaptColor = false; + @Input() public center = false; + @Input() public textTransform: 'capitalize' | 'uppercase' = 'uppercase'; +} diff --git a/src/components/common/title/title.html b/src/components/common/title/title.html new file mode 100644 index 0000000..963fa99 --- /dev/null +++ b/src/components/common/title/title.html @@ -0,0 +1,14 @@ +

{{ text }}

diff --git a/src/components/common/title/title.scss b/src/components/common/title/title.scss new file mode 100644 index 0000000..a716530 --- /dev/null +++ b/src/components/common/title/title.scss @@ -0,0 +1,20 @@ +h1 { + font-family: Inter, sans-serif; + font-style: normal; + font-weight: 400; + font-size: calc(18px * var(--font-size)); + margin: calc(17px / 2) 0; + color: var(--text-color); +} + +.dark-mode { + color: var(--text-color-dark-bg); +} + +.centered { + text-align: center; +} + +.themed { + color: var(--text-color-dynamic); +} diff --git a/src/components/components.module.ts b/src/components/components.module.ts new file mode 100644 index 0000000..f7e03af --- /dev/null +++ b/src/components/components.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { CommonComponentsModule } from './common/common.module'; +import { DesktopComponentsModule } from './desktop/desktop.module'; +import { MobileComponentsModule } from './mobile/mobile.module'; + +@NgModule({ + declarations: [], + exports: [MobileComponentsModule, DesktopComponentsModule, CommonComponentsModule], + imports: [RouterModule], +}) +export class ComponentsModule {} diff --git a/src/components/desktop/desktop.module.ts b/src/components/desktop/desktop.module.ts new file mode 100644 index 0000000..78acc72 --- /dev/null +++ b/src/components/desktop/desktop.module.ts @@ -0,0 +1,14 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; + +import { DesktopHeaderComponent } from './header/header.component'; +import { DesktopNavbarComponent } from './navbar/navbar.component'; +import { CommonComponentsModule } from '../common/common.module'; + +@NgModule({ + declarations: [DesktopHeaderComponent, DesktopNavbarComponent], + exports: [DesktopHeaderComponent, DesktopNavbarComponent], + imports: [CommonModule, CommonComponentsModule, TranslateModule], +}) +export class DesktopComponentsModule {} diff --git a/src/components/desktop/header/header.component.spec.ts b/src/components/desktop/header/header.component.spec.ts new file mode 100644 index 0000000..991d644 --- /dev/null +++ b/src/components/desktop/header/header.component.spec.ts @@ -0,0 +1,51 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { DesktopHeaderComponent } from './header.component'; +import { CommonComponentsModule } from '../../common/common.module'; + +describe('DesktopHeaderComponent', () => { + let component: DesktopHeaderComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DesktopHeaderComponent], + imports: [TranslateModule.forRoot(), CommonComponentsModule], + providers: [PageService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DesktopHeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('triggerSideMenuProfile', () => { + it('should open the profile menu when triggered', () => { + component.triggerSideMenuProfile(); + expect(component.profileOpened).toBeTrue(); + }); + }); + + describe('triggerSideMenuConnection', () => { + it('should open the connection menu when triggered', () => { + component.triggerSideMenuConnection(); + expect(component.connectionOpened).toBeTrue(); + }); + }); + + describe('triggerSideMenuOptions', () => { + it('should open the options menu when triggered', () => { + component.triggerSideMenuOptions(); + expect(component.optionsOpened).toBeTrue(); + }); + }); +}); diff --git a/src/components/desktop/header/header.component.ts b/src/components/desktop/header/header.component.ts new file mode 100644 index 0000000..bf55176 --- /dev/null +++ b/src/components/desktop/header/header.component.ts @@ -0,0 +1,59 @@ +import type { imageURL } from '#types'; +import type { OutputErrorResponseDto } from '#types/api'; + +import { Component, Inject } from '@angular/core'; + +import { ApiError } from '@services/api.service'; +import { PageService } from '@services/page.service'; +import { SnackbarService } from '@services/snackbar.service'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-desktop-header', + templateUrl: './header.html', + styleUrls: ['./header.scss'], +}) +export class DesktopHeaderComponent { + public profileOpened = false; + public optionsOpened = false; + public connectionOpened = false; + + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(UserService) public readonly userService: UserService, + @Inject(SnackbarService) public readonly snackbar: SnackbarService, + ) { + if (this.userService.isLoggedIn()) { + this.userService.userPicture(this.userService.logged_user_id).subscribe({ + next: (picture) => (this.userPicture = picture), + error: (err: ApiError) => { + console.error(err); + this.snackbar.error(err.error.message, err.error.errors, err.error.statusCode); + }, + }); + + this.userService.userNotificationsCount(this.userService.logged_user_id).subscribe({ + next: (count) => (this.userNotificationsCount = count), + error: (err: ApiError) => { + console.error(err); + this.snackbar.error(err.error.message, err.error.errors, err.error.statusCode); + }, + }); + } + } + + public userPicture?: imageURL; + public userNotificationsCount?: number; + + public triggerSideMenuProfile(): void { + this.profileOpened = !this.profileOpened; + } + + public triggerSideMenuConnection(): void { + this.connectionOpened = !this.connectionOpened; + } + + public triggerSideMenuOptions(): void { + this.optionsOpened = !this.optionsOpened; + } +} diff --git a/src/components/desktop/header/header.html b/src/components/desktop/header/header.html new file mode 100644 index 0000000..39abaad --- /dev/null +++ b/src/components/desktop/header/header.html @@ -0,0 +1,35 @@ +
+
+ AE's logo +
+ Association des Étudiants + de l'université de technologie de Belfort-Montbéliard +
+
+ +
+ + + + + +
+
+ + + + + + + + + + + + diff --git a/src/components/desktop/header/header.scss b/src/components/desktop/header/header.scss new file mode 100644 index 0000000..46f2649 --- /dev/null +++ b/src/components/desktop/header/header.scss @@ -0,0 +1,82 @@ +.header { + display: flex; + justify-content: space-between; + align-items: center; + background-color: var(--navbar-background-color); + height: 70px; + padding-left: 10px; + + > .title { + cursor: pointer; + display: flex; + align-items: center; + height: 64px; + gap: 10px; + + > img { + width: 64px; + height: 64px; + } + + > .text { + color: var(--navbar-text-color); + display: flex; + flex-direction: column; + font-family: Roboto, sans-serif; + font-weight: 500; + margin-bottom: 5px; + + > .big { + font-size: calc(20px * var(--font-size)); + } + + > .small { + font-size: calc(8px * var(--font-size)); + text-transform: uppercase; + } + } + + &:hover > .text { + color: var(--dark-blue); + } + } + + > .icons { + display: flex; + fill: var(--navbar-text-color); + align-items: center; + gap: 16px; + padding: 0 16px; + + > .icon { + cursor: pointer; + width: 32px; + height: 32px; + fill: var(--navbar-text-color); + + &.search { + width: 22px; + height: 22px; + } + + &:hover { + fill: var(--dark-blue); + } + } + } +} + +.side-menu { + position: absolute; + top: 0; + z-index: 1; + height: 100vh; + width: 100vw; + animation: fade 0.5s ease-in-out; + background-color: var(--darkened); + display: none; + + &.open { + display: block; + } +} diff --git a/src/components/desktop/navbar/navbar.component.ts b/src/components/desktop/navbar/navbar.component.ts new file mode 100644 index 0000000..d0dab27 --- /dev/null +++ b/src/components/desktop/navbar/navbar.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject } from '@angular/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-desktop-navbar', + templateUrl: './navbar.html', + styleUrls: ['./navbar.scss'], +}) +export class DesktopNavbarComponent { + public constructor( + @Inject(UserService) public readonly u: UserService, + @Inject(PageService) public readonly page: PageService, + ) {} + + public openFavorites() { + window.alert('Not implemented yet'); + } +} diff --git a/src/components/desktop/navbar/navbar.html b/src/components/desktop/navbar/navbar.html new file mode 100644 index 0000000..e04a3b3 --- /dev/null +++ b/src/components/desktop/navbar/navbar.html @@ -0,0 +1,22 @@ + diff --git a/src/components/desktop/navbar/navbar.scss b/src/components/desktop/navbar/navbar.scss new file mode 100644 index 0000000..46cf716 --- /dev/null +++ b/src/components/desktop/navbar/navbar.scss @@ -0,0 +1,48 @@ +.navbar { + width: 100%; + display: flex; + flex-direction: row; + align-items: center; + background-color: var(--gray1); + height: 40px; + box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); + + &.centered { + justify-content: center; + gap: 20px; + } + + &.full { + justify-content: flex-start; + } + + > .link { + cursor: pointer; + height: 100%; + padding: 0 30px; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + + &:hover { + background-color: var(--gray2); + } + + > .icon { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + fill: var(--text-color-dynamic); + } + + > span { + text-transform: uppercase; + font-family: Roboto, sans-serif; + font-size: calc(12px * var(--font-size)); + color: var(--text-color-dynamic); + } + } +} diff --git a/src/components/mobile/header/header.component.spec.ts b/src/components/mobile/header/header.component.spec.ts new file mode 100644 index 0000000..df570d4 --- /dev/null +++ b/src/components/mobile/header/header.component.spec.ts @@ -0,0 +1,52 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +import { MobileHeaderComponent } from './header.component'; +import { MobileComponentsModule } from '../mobile.module'; + +describe('MobileHeaderComponent', () => { + let component: MobileHeaderComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MobileHeaderComponent], + imports: [TranslateModule.forRoot(), MobileComponentsModule], + providers: [PageService, UserService, TranslateService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MobileHeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('triggerSideMenuProfile', () => { + it('should open the profile menu when triggered', () => { + component.triggerSideMenuProfile(); + expect(component.profileOpened).toBeTrue(); + }); + }); + + describe('triggerSideMenuConnection', () => { + it('should open the connection menu when triggered', () => { + component.triggerSideMenuConnection(); + expect(component.connectionOpened).toBeTrue(); + }); + }); + + describe('triggerSideMenuOptions', () => { + it('should open the options menu when triggered', () => { + component.triggerSideMenuOptions(); + expect(component.optionsOpened).toBeTrue(); + }); + }); +}); diff --git a/src/components/mobile/header/header.component.ts b/src/components/mobile/header/header.component.ts new file mode 100644 index 0000000..002084f --- /dev/null +++ b/src/components/mobile/header/header.component.ts @@ -0,0 +1,68 @@ +import type { imageURL } from '#types'; +import type { OutputErrorResponseDto, OutputUserDto } from '#types/api'; + +import { Component, Inject } from '@angular/core'; + +import { ApiError } from '@services/api.service'; +import { PageService } from '@services/page.service'; +import { SnackbarService } from '@services/snackbar.service'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-mobile-header', + templateUrl: './header.html', + styleUrls: ['./header.scss'], +}) +export class MobileHeaderComponent { + public profileOpened = false; + public optionsOpened = false; + public connectionOpened = false; + + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(UserService) public readonly userService: UserService, + @Inject(SnackbarService) public readonly snackbar: SnackbarService, + ) { + if (userService.isLoggedIn()) { + this.userService.user(this.userService.logged_user_id).subscribe({ + next: (user) => (this.user = user), + error: (err: ApiError) => { + console.error(err); + this.snackbar.error(err.error.message, err.error.errors, err.error.statusCode); + }, + }); + + this.userService.userPicture(this.userService.logged_user_id).subscribe({ + next: (picture) => (this.userPicture = picture), + error: (err: ApiError) => { + console.error(err); + this.snackbar.error(err.error.message, err.error.errors, err.error.statusCode); + }, + }); + + this.userService.userNotificationsCount(this.userService.logged_user_id).subscribe({ + next: (count) => (this.userNotificationsCount = count), + error: (err: ApiError) => { + console.error(err); + this.snackbar.error(err.error.message, err.error.errors, err.error.statusCode); + }, + }); + } + } + + public user?: OutputUserDto; + public userPicture?: imageURL; + public userNotificationsCount?: number; + + public triggerSideMenuProfile(): void { + this.profileOpened = !this.profileOpened; + } + + public triggerSideMenuConnection(): void { + this.connectionOpened = !this.connectionOpened; + } + + public triggerSideMenuOptions(): void { + this.optionsOpened = !this.optionsOpened; + } +} diff --git a/src/components/mobile/header/header.html b/src/components/mobile/header/header.html new file mode 100644 index 0000000..d4afe93 --- /dev/null +++ b/src/components/mobile/header/header.html @@ -0,0 +1,36 @@ +
+ +
+ + + +
+
+ + + + + + + + + + + + diff --git a/src/components/mobile/header/header.scss b/src/components/mobile/header/header.scss new file mode 100644 index 0000000..acd9194 --- /dev/null +++ b/src/components/mobile/header/header.scss @@ -0,0 +1,41 @@ +.header { + background-color: var(--navbar-background-color); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 10px; + height: 70px; + + > .logo { + width: 64px; + height: 64px; + } + + > .icons { + display: flex; + padding: 16px 5px; + gap: 16px; + + > .icon { + width: 32px; + height: 32px; + fill: var(--navbar-text-color); + cursor: pointer; + } + } +} + +.side-menu { + position: absolute; + top: 0; + z-index: 1; + height: 100vh; + width: 100vw; + animation: fade 0.5s ease-in-out; + background-color: var(--darkened); + display: none; + + &.open { + display: block; + } +} diff --git a/src/components/mobile/mobile.module.ts b/src/components/mobile/mobile.module.ts new file mode 100644 index 0000000..298e0dd --- /dev/null +++ b/src/components/mobile/mobile.module.ts @@ -0,0 +1,15 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; + +import { MobileHeaderComponent } from './header/header.component'; +import { MobileNavbarComponent } from './navbar/navbar.component'; +import { CommonComponentsModule } from '../common/common.module'; + +@NgModule({ + declarations: [MobileHeaderComponent, MobileNavbarComponent], + exports: [MobileHeaderComponent, MobileNavbarComponent], + imports: [CommonModule, CommonComponentsModule, TranslateModule, RouterModule], +}) +export class MobileComponentsModule {} diff --git a/src/components/mobile/navbar/navbar.component.spec.ts b/src/components/mobile/navbar/navbar.component.spec.ts new file mode 100644 index 0000000..04a2866 --- /dev/null +++ b/src/components/mobile/navbar/navbar.component.spec.ts @@ -0,0 +1,29 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +import { MobileNavbarComponent } from './navbar.component'; +import { MobileComponentsModule } from '../mobile.module'; + +describe('MobileNavbarComponent', () => { + let component: MobileNavbarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MobileNavbarComponent], + imports: [TranslateModule.forRoot(), MobileComponentsModule], + providers: [PageService, UserService], + }).compileComponents(); + + fixture = TestBed.createComponent(MobileNavbarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/components/mobile/navbar/navbar.component.ts b/src/components/mobile/navbar/navbar.component.ts new file mode 100644 index 0000000..633acc1 --- /dev/null +++ b/src/components/mobile/navbar/navbar.component.ts @@ -0,0 +1,16 @@ +import { Component, Inject } from '@angular/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-mobile-navbar', + templateUrl: './navbar.html', + styleUrls: ['./navbar.scss'], +}) +export class MobileNavbarComponent { + public constructor( + @Inject(UserService) public readonly u: UserService, + @Inject(PageService) public readonly page: PageService, + ) {} +} diff --git a/src/components/mobile/navbar/navbar.html b/src/components/mobile/navbar/navbar.html new file mode 100644 index 0000000..5d35e48 --- /dev/null +++ b/src/components/mobile/navbar/navbar.html @@ -0,0 +1,13 @@ + diff --git a/src/components/mobile/navbar/navbar.scss b/src/components/mobile/navbar/navbar.scss new file mode 100644 index 0000000..152466c --- /dev/null +++ b/src/components/mobile/navbar/navbar.scss @@ -0,0 +1,34 @@ +.navbar { + height: 40px; + background-color: var(--gray1); + display: flex; + justify-content: space-between; + + > .left { + width: 100%; + justify-content: flex-start; + gap: 16px; + } + + > .right { + justify-content: flex-end; + gap: 8px; + } + + > .left, + > .right { + display: flex; + align-items: center; + padding: 0 10px; + + > .icon { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + fill: var(--text-color-dynamic); + cursor: pointer; + } + } +} diff --git a/src/directives/date.directive.spec.ts b/src/directives/date.directive.spec.ts new file mode 100644 index 0000000..317902c --- /dev/null +++ b/src/directives/date.directive.spec.ts @@ -0,0 +1,54 @@ +import { FormControl } from '@angular/forms'; + +import { ageMaxValidator, ageMinValidator, notInFutureValidator } from './date.directive'; + +describe('ageMinValidator', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(ageMinValidator()(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('2000-01-01'); + expect(ageMinValidator()(control)).toBeNull(); + }); + + it('should return an error if the control is invalid', () => { + const control = new FormControl('2000-01-01'); + expect(ageMinValidator(1000)(control)).toEqual({ age_minimum: true }); + }); +}); + +describe('ageMaxValidator', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(ageMaxValidator()(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('2000-01-01'); + expect(ageMaxValidator()(control)).toBeNull(); + }); + + it('should return an error if the control is invalid', () => { + const control = new FormControl('2001-01-01'); + expect(ageMaxValidator(1)(control)).toEqual({ age_maximum: true }); + }); +}); + +describe('notInFutureValidator', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(notInFutureValidator(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('2000-01-01'); + expect(notInFutureValidator(control)).toBeNull(); + }); + + it('should return an error if the control is invalid', () => { + const control = new FormControl('3000-01-01'); + expect(notInFutureValidator(control)).toEqual({ not_in_future: true }); + }); +}); diff --git a/src/directives/date.directive.ts b/src/directives/date.directive.ts new file mode 100644 index 0000000..b36071a --- /dev/null +++ b/src/directives/date.directive.ts @@ -0,0 +1,60 @@ +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; + +import { environment } from 'src/environments/environment'; + +/** + * Check if the date is required if the age is below the minAge + ** Used to check if the user is a minor & make the field required + * @param {number} minAge The minimum age for the field to be not required + * @param {number} age The age of the user to check + * @returns {ValidatorFn} The angular validator function + */ +export function requiredIfBelow(minAge: number, age: number): ValidatorFn | null { + return (control: AbstractControl): ValidationErrors | null => { + if (!control.value) return null; + + return minAge > age ? { required_under: true } : null; + }; +} + +/** + * Check if the field is at least the min age + * @param {number} min The minimum age to be accepted + * @returns {ValidatorFn} The angular validator function + */ +export function ageMinValidator(min = environment.USERS.MIN_AGE): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (!control.value) return null; + + const year = new Date().getFullYear(); + const birthDateYear = new Date(control.value).getFullYear(); + return birthDateYear > year - min ? { age_minimum: true } : null; + }; +} + +/** + * Check if the field is at most the max age + * @param {number} max The maximum age to be accepted + * @returns {ValidatorFn} The angular validator function + */ +export function ageMaxValidator(max = environment.USERS.MAX_AGE): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (!control.value) return null; + + const year = new Date().getFullYear(); + const birthDateYear = new Date(control.value).getFullYear(); + return birthDateYear < year - max ? { age_maximum: true } : null; + }; +} + +/** + * Check that the field is not set in the future + * @param {AbstractControl} control The control to check + * @returns {ValidationErrors | null} The error if the field is in the future + */ +export function notInFutureValidator(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + + const forbidden = new Date(control.value).getTime() > new Date().getTime(); + return forbidden ? { not_in_future: true } : null; +} diff --git a/src/directives/forbidden_email.directive.spec.ts b/src/directives/forbidden_email.directive.spec.ts new file mode 100644 index 0000000..604f80f --- /dev/null +++ b/src/directives/forbidden_email.directive.spec.ts @@ -0,0 +1,20 @@ +import { FormControl } from '@angular/forms'; + +import { forbiddenEmailValidator } from './forbidden_email.directive'; + +describe('forbiddenEmailValidator', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(forbiddenEmailValidator('@utbm.fr')(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('@gmail.com'); + expect(forbiddenEmailValidator('@utbm.fr')(control)).toBeNull(); + }); + + it('should return error if the control is not valid', () => { + const control = new FormControl('someone@utbm.fr'); + expect(forbiddenEmailValidator('@utbm.fr')(control)).toEqual({ forbidden_email: true }); + }); +}); diff --git a/src/directives/forbidden_email.directive.ts b/src/directives/forbidden_email.directive.ts new file mode 100644 index 0000000..3152090 --- /dev/null +++ b/src/directives/forbidden_email.directive.ts @@ -0,0 +1,18 @@ +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; + +const WHITELIST = ['ae@utbm.fr', 'ae.info@utbm.fr']; + +/** + * Check if the given email is not a forbidden one. + * @param {...string} emails Array of forbidden emails (e.g. '@utbm.fr') + * @returns {ValidatorFn} The angular validator function + */ +export function forbiddenEmailValidator(...emails: string[]): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const forbidden = emails.find( + (e) => control.value && control.value.endsWith(e) && !WHITELIST.includes(control.value), + ); + + return forbidden ? { forbidden_email: true } : null; + }; +} diff --git a/src/directives/index.spec.ts b/src/directives/index.spec.ts new file mode 100644 index 0000000..a947d02 --- /dev/null +++ b/src/directives/index.spec.ts @@ -0,0 +1,24 @@ +import { FormControl } from '@angular/forms'; + +import { getErrors } from '.'; + +describe('getErrors', () => { + it('should return empty array if the control does not have errors', () => { + const control = new FormControl(); + expect(getErrors(control)).toEqual([]); + }); + + it('should return empty array if the control is not touched', () => { + const control = new FormControl(''); + control.setErrors({ required: true }); + expect(getErrors(control)).toEqual([]); + }); + + it('should return array of errors if the control has errors', () => { + const control = new FormControl(''); + control.setErrors({ required: true, minlength: true }); + control.markAsTouched(); + + expect(getErrors(control)).toEqual(['required', 'minlength']); + }); +}); diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 0000000..d6341d2 --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,34 @@ +import { AbstractControl } from '@angular/forms'; + +import { ageMinValidator, ageMaxValidator, notInFutureValidator, requiredIfBelow } from './date.directive'; +import { forbiddenEmailValidator } from './forbidden_email.directive'; +import { nameValidator } from './name.directive'; +import { + hasOneDigit, + hasOneSpecialCharacter, + hasOneUppercase, + hasOneLowercase, + hasNoDuplicateCharacters, + passwordsMatchValidator, +} from './password.directive'; + +export class CustomValidators { + public static forbiddenEmailValidator = forbiddenEmailValidator; + public static requiredIfBelow = requiredIfBelow; + public static ageMinValidator = ageMinValidator; + public static ageMaxValidator = ageMaxValidator; + public static notInFutureValidator = notInFutureValidator; + public static nameValidator = nameValidator; + public static hasOneDigit = hasOneDigit; + public static hasOneSpecialCharacter = hasOneSpecialCharacter; + public static hasOneUppercase = hasOneUppercase; + public static hasOneLowercase = hasOneLowercase; + public static hasNoDuplicateCharacters = hasNoDuplicateCharacters; + public static passwordsMatchValidator = passwordsMatchValidator; +} + +export function getErrors(control: AbstractControl) { + if (!control.errors) return []; + if (control.pristine && !control.touched) return []; + return Object.keys(control.errors).map((key) => key.toString()); +} diff --git a/src/directives/name.directive.spec.ts b/src/directives/name.directive.spec.ts new file mode 100644 index 0000000..f69370f --- /dev/null +++ b/src/directives/name.directive.spec.ts @@ -0,0 +1,26 @@ +import { FormControl } from '@angular/forms'; + +import { nameValidator } from './name.directive'; + +describe('nameValidator', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(nameValidator(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const values = ['John', 'John Doe', 'John-Doe', "John D'oe"]; + values.forEach((value) => { + const control = new FormControl(value); + expect(nameValidator(control)).toEqual(null); + }); + }); + + it('should return an error if the control is invalid', () => { + const values = ['John ', ' John', 'John Doe', 'John.Doe', 'John_Doe', '!John']; + values.forEach((value) => { + const control = new FormControl(value); + expect(nameValidator(control)).toEqual({ invalid_name: true }); + }); + }); +}); diff --git a/src/directives/name.directive.ts b/src/directives/name.directive.ts new file mode 100644 index 0000000..456f005 --- /dev/null +++ b/src/directives/name.directive.ts @@ -0,0 +1,9 @@ +import { AbstractControl, ValidationErrors } from '@angular/forms'; + +export function nameValidator(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + + // check if the name contains only letters (from any language), hyphens and apostrophes + const regex = new RegExp(/^[\p{L}'-]+(?: [\p{L}'-]+)*$/u); + return regex.test(control.value) === false ? { invalid_name: true } : null; +} diff --git a/src/directives/password.directive.spec.ts b/src/directives/password.directive.spec.ts new file mode 100644 index 0000000..7adec08 --- /dev/null +++ b/src/directives/password.directive.spec.ts @@ -0,0 +1,115 @@ +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; + +import { + hasNoDuplicateCharacters, + hasOneDigit, + hasOneLowercase, + hasOneSpecialCharacter, + hasOneUppercase, + passwordsMatchValidator, +} from './password.directive'; + +describe('hasOneDigit', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(hasOneDigit(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('123'); + expect(hasOneDigit(control)).toBeNull(); + }); + + it('should return error if the control is not valid', () => { + const control = new FormControl('abc'); + expect(hasOneDigit(control)).toEqual({ has_one_digit: true }); + }); +}); + +describe('hasOneSpecialCharacter', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(hasOneSpecialCharacter(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('@bc'); + expect(hasOneSpecialCharacter(control)).toBeNull(); + }); + + it('should return error if the control is not valid', () => { + const control = new FormControl('abc'); + expect(hasOneSpecialCharacter(control)).toEqual({ has_one_special_character: true }); + }); +}); + +describe('hasOneLowercase', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(hasOneLowercase(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('abc'); + expect(hasOneLowercase(control)).toBeNull(); + }); + + it('should return error if the control is not valid', () => { + const control = new FormControl('ABC'); + expect(hasOneLowercase(control)).toEqual({ has_one_lowercase: true }); + }); +}); + +describe('hasOneUppercase', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(hasOneUppercase(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('ABC'); + expect(hasOneUppercase(control)).toBeNull(); + }); + + it('should return error if the control is not valid', () => { + const control = new FormControl('abc'); + expect(hasOneUppercase(control)).toEqual({ has_one_uppercase: true }); + }); +}); + +describe('hasNoDuplicateCharacters', () => { + it('should return null if the control is empty', () => { + const control = new FormControl(); + expect(hasNoDuplicateCharacters(control)).toBeNull(); + }); + + it('should return null if the control is valid', () => { + const control = new FormControl('abc'); + expect(hasNoDuplicateCharacters(control)).toBeNull(); + }); + + it('should return error if the control is not valid', () => { + const control = new FormControl('aabc'); + expect(hasNoDuplicateCharacters(control)).toEqual({ has_no_duplicate_characters: true }); + }); +}); + +describe('passwordsMatchValidator', () => { + const fb = new FormBuilder(); + const control: FormGroup = fb.group({ + password: ['', [Validators.required]], + passwordConfirm: ['', [Validators.required]], + }); + + it('should return error if the passwords do not match', () => { + control.get('password')?.setValue('abc'); + control.get('passwordConfirm')?.setValue('def'); + expect(passwordsMatchValidator()(control)).toEqual({ passwords_match: true }); + }); + + it('should return null if the passwords match', () => { + control.get('password')?.setValue('abc'); + control.get('passwordConfirm')?.setValue('abc'); + expect(passwordsMatchValidator()(control)).toBeNull(); + }); +}); diff --git a/src/directives/password.directive.ts b/src/directives/password.directive.ts new file mode 100644 index 0000000..64e1699 --- /dev/null +++ b/src/directives/password.directive.ts @@ -0,0 +1,39 @@ +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; + +export function hasOneDigit(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + return /\d/.test(control.value) === false ? { has_one_digit: true } : null; +} + +export function hasOneSpecialCharacter(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + return /[\W_]+/.test(control.value) === false ? { has_one_special_character: true } : null; +} + +export function hasOneUppercase(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + return /[A-Z]/.test(control.value) === false ? { has_one_uppercase: true } : null; +} + +export function hasOneLowercase(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + return /[a-z]/.test(control.value) === false ? { has_one_lowercase: true } : null; +} + +export function hasNoDuplicateCharacters(control: AbstractControl): ValidationErrors | null { + if (!control.value) return null; + return control.value.match(/([a-z])\1+/g) !== null || + control.value.match(/([A-Z])\1+/g) !== null || + control.value.match(/([0-9])\1+/g) !== null + ? { has_no_duplicate_characters: true } + : null; +} + +export function passwordsMatchValidator(password_field = 'password', confirm_field = 'password_confirm'): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const password = control.get(password_field); + const passwordConfirm = control.get(confirm_field); + + return password?.value === passwordConfirm?.value ? null : { passwords_match: true }; + }; +} diff --git a/src/environments/environment.dev.ts b/src/environments/environment.dev.ts new file mode 100644 index 0000000..518d00f --- /dev/null +++ b/src/environments/environment.dev.ts @@ -0,0 +1,18 @@ +export const environment = { + PRODUCTION: false, + HCAPTCHA_SITE_KEY: '10000000-ffff-ffff-ffff-000000000001', + API_URL: 'http://localhost:3000', + DELAY_UPDATE_PROFILE_PICTURE: 604800, + + USERS: { + MIN_AGE: 13, + MAX_AGE: 100, + + MIN_NAME_LENGTH: 2, + MAX_NAME_LENGTH: 50, + + MIN_PASSWORD_LENGTH: 8, + }, +}; + +export type Environment = typeof environment; diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts new file mode 100644 index 0000000..2d53c56 --- /dev/null +++ b/src/environments/environment.prod.ts @@ -0,0 +1,6 @@ +import { environment as devEnv, Environment } from './environment.dev'; + +export const environment: Environment = Object.merge(devEnv, { + PRODUCTION: true, + HCAPTCHA_SITE_KEY: '', // TODO: Add hCaptcha site key (log with the github bot account) +}); diff --git a/src/environments/environment.ts b/src/environments/environment.ts new file mode 100644 index 0000000..37f6edb --- /dev/null +++ b/src/environments/environment.ts @@ -0,0 +1 @@ +export * from './environment.dev'; diff --git a/src/exported b/src/exported new file mode 160000 index 0000000..cc12a9c --- /dev/null +++ b/src/exported @@ -0,0 +1 @@ +Subproject commit cc12a9ce00080049e04eea3e99054cf69252144f diff --git a/src/guards/auth.guard.ts b/src/guards/auth.guard.ts new file mode 100644 index 0000000..6f3af2e --- /dev/null +++ b/src/guards/auth.guard.ts @@ -0,0 +1,26 @@ +import { Inject, Injectable } from '@angular/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +@Injectable() +export class AuthGuard { + constructor( + @Inject(PageService) private readonly page: PageService, + @Inject(UserService) private readonly userService: UserService, + ) {} + + public isLoggedIn(): boolean { + if (this.userService.isLoggedIn()) return true; + + this.page.to(['login']); + return false; + } + + public isLoggedOut(): boolean { + if (!this.userService.isLoggedIn()) return true; + + this.page.to(['home']); + return false; + } +} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..faf38ee --- /dev/null +++ b/src/index.html @@ -0,0 +1,24 @@ + + + + + AE UTBM + + + + + + + + + + + + + + + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..6aa191c --- /dev/null +++ b/src/main.ts @@ -0,0 +1,8 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from '@app.module'; +import '@exported/global/utils'; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/src/pages/404/not-found.component.spec.ts b/src/pages/404/not-found.component.spec.ts new file mode 100644 index 0000000..c5782c7 --- /dev/null +++ b/src/pages/404/not-found.component.spec.ts @@ -0,0 +1,30 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { NotFoundComponent } from './not-found.component'; +import { CommonComponentsModule } from '../../components/common/common.module'; + +describe('NotFoundComponent', () => { + let component: NotFoundComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [NotFoundComponent], + imports: [TranslateModule.forRoot(), CommonComponentsModule], + providers: [PageService, TranslateService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotFoundComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pages/404/not-found.component.ts b/src/pages/404/not-found.component.ts new file mode 100644 index 0000000..69c9769 --- /dev/null +++ b/src/pages/404/not-found.component.ts @@ -0,0 +1,12 @@ +import { Component, Inject } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-not-found', + templateUrl: './not-found.html', + styleUrls: ['./not-found.scss'], +}) +export class NotFoundComponent { + public constructor(@Inject(PageService) public readonly page: PageService) {} +} diff --git a/src/pages/404/not-found.html b/src/pages/404/not-found.html new file mode 100644 index 0000000..4068d14 --- /dev/null +++ b/src/pages/404/not-found.html @@ -0,0 +1,10 @@ +
+ + + + + +

{{ '404.description' | translate }}

+ + +
diff --git a/src/pages/404/not-found.scss b/src/pages/404/not-found.scss new file mode 100644 index 0000000..7544d63 --- /dev/null +++ b/src/pages/404/not-found.scss @@ -0,0 +1,26 @@ +.content { + min-height: 100vh; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + font-family: Inter, sans-serif; + + > .description { + color: var(--text-color-dynamic); + text-align: center; + margin: 20px; + } + + > .logo { + width: 200px; + height: 200px; + margin-bottom: 20px; + } + + > .button { + margin-top: 20px; + } +} diff --git a/src/pages/forgot_password/forgot_password.component.spec.ts b/src/pages/forgot_password/forgot_password.component.spec.ts new file mode 100644 index 0000000..826b7b9 --- /dev/null +++ b/src/pages/forgot_password/forgot_password.component.spec.ts @@ -0,0 +1,51 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +import { ForgotPasswordComponent } from './forgot_password.component'; +import { CommonComponentsModule } from '../../components/common/common.module'; + +describe('ForgotPasswordComponent', () => { + let component: ForgotPasswordComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ForgotPasswordComponent], + imports: [TranslateModule.forRoot(), CommonComponentsModule, FormsModule, ReactiveFormsModule], + providers: [PageService, TranslateService, UserService, FormBuilder], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ForgotPasswordComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('getError', () => { + it('should return the error message', () => { + component.formGroup.controls['email'].markAsTouched(); // left the field without entering anything + component.formGroup.controls['email'].setErrors({ email: true }); // invalid email + + Object.keys(component.formGroup.controls['email'].errors ?? {}).forEach((key) => { + expect(component.getError(key)).toEqual(`global.errors.${key}`); + }); + }); + }); + + describe('sendEmail', () => { + it('should send the email', () => { + component.formGroup.controls['email'].setValue('exemple@domain.net'); + component.sendEmail(); + expect(true).toBeTrue(); // TODO: add a test once the API is ready + }); + }); +}); diff --git a/src/pages/forgot_password/forgot_password.component.ts b/src/pages/forgot_password/forgot_password.component.ts new file mode 100644 index 0000000..de1b362 --- /dev/null +++ b/src/pages/forgot_password/forgot_password.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; + +import { CustomValidators, getErrors } from '@directives'; +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-forgot-password', + templateUrl: './forgot_password.html', + styleUrls: ['./forgot_password.scss'], +}) +export class ForgotPasswordComponent { + public formGroup: FormGroup = this.fb.group({ + email: ['', [Validators.required, Validators.email, CustomValidators.forbiddenEmailValidator('@utbm.fr')]], + }); + + public constructor( + @Inject(TranslateService) public readonly t: TranslateService, + @Inject(PageService) public readonly page: PageService, + @Inject(FormBuilder) private readonly fb: FormBuilder, + ) {} + + public errors(field: string): string[] { + return getErrors(this.formGroup.controls[field]); + } + + public getError(field: string): string { + return `global.errors.${field}`; + } + + public sendEmail(): void { + return; + } +} diff --git a/src/pages/forgot_password/forgot_password.html b/src/pages/forgot_password/forgot_password.html new file mode 100644 index 0000000..fca247c --- /dev/null +++ b/src/pages/forgot_password/forgot_password.html @@ -0,0 +1,35 @@ +
+ +
+ +
+ Association des Étudiants + de l'université de technologie de Belfort-Montbéliard +
+
+ +
+ + +
+ {{ 'forgot_password.description' | translate }} +
+ +
+
+
+ + +
+
+ {{ getError(error) | translate }} +
+
+
+ + +
+
diff --git a/src/pages/forgot_password/forgot_password.scss b/src/pages/forgot_password/forgot_password.scss new file mode 100644 index 0000000..07dee9c --- /dev/null +++ b/src/pages/forgot_password/forgot_password.scss @@ -0,0 +1,140 @@ +main { + background-color: var(--gray3); + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + gap: 40px; + padding: 40px 20px 60px; + + >.warning { + font-family: Roboto, sans-serif; + background-color: var(--orange-hover); + color: var(--text-color-dark-bg); + border: 1px solid var(--orange); + padding: 10px; + width: 100%; + max-width: 400px; + border-radius: 5px; + text-align: center; + } + + >.header { + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + + >.logo { + width: 200px; + height: 130px; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + } + + >.text { + display: flex; + flex-direction: column; + color: var(--text-color-dark-bg); + font-family: Inter, sans-serif; + + >.title { + font-size: calc(25.5px * var(--font-size)); + } + + >.subtitle { + text-transform: uppercase; + font-size: calc(10px * var(--font-size)); + } + } + + &:hover>.text { + color: var(--dark-blue); + } + } + + >form { + width: 100%; + max-width: 400px; + display: flex; + flex-direction: column; + gap: 30px; + + >.form-head { + width: 100%; + } + + >.form-description { + color: var(--text-color-dark-bg); + font-family: Inter, sans-serif; + font-size: calc(14px * var(--font-size)); + font-style: italic; + } + + >.form-body { + display: flex; + flex-direction: column; + gap: 10px; + + >.global-link { + text-align: center; + } + + >.input-container { + width: 100%; + display: flex; + flex-direction: column; + gap: 5px; + + >.error { + font-family: Roboto, sans-serif; + color: var(--red); + font-size: calc(12px * var(--font-size)); + line-height: 14px; + margin-left: calc(32px + 5px); + display: flex; + flex-direction: column; + } + + >.input { + width: 100%; + display: flex; + gap: 5px; + + >.icon { + width: 16px; + height: 16px; + margin: 8px; + } + + >input { + font-family: Roboto, sans-serif; + font-weight: normal; + color: var(--text-color-dark-bg); + background-color: var(--gray4); + width: 100%; + border: none; + border-radius: 5px; + height: 32px; + padding: 5px 5px 5px 10px; + display: flex; + justify-content: center; + align-items: center; + + &::placeholder { + color: var(--text-color-dark-bg-placeholder); + font-size: calc(14px * var(--font-size)); + } + } + } + } + } + + >.form-button { + width: 100%; + } + } +} \ No newline at end of file diff --git a/src/pages/home/home.component.spec.ts b/src/pages/home/home.component.spec.ts new file mode 100644 index 0000000..a028f2c --- /dev/null +++ b/src/pages/home/home.component.spec.ts @@ -0,0 +1,29 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +import { HomeComponent } from './home.component'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HomeComponent], + imports: [TranslateModule.forRoot()], + providers: [TranslateService, PageService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pages/home/home.component.ts b/src/pages/home/home.component.ts new file mode 100644 index 0000000..77ba1fa --- /dev/null +++ b/src/pages/home/home.component.ts @@ -0,0 +1,16 @@ +import { Component, Inject } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-home', + templateUrl: './home.html', + styleUrls: [], +}) +export class HomeComponent { + public constructor( + @Inject(TranslateService) public readonly t: TranslateService, + @Inject(PageService) public readonly page: PageService, + ) {} +} diff --git a/src/pages/home/home.html b/src/pages/home/home.html new file mode 100644 index 0000000..2fd89ce --- /dev/null +++ b/src/pages/home/home.html @@ -0,0 +1 @@ +Home diff --git a/src/pages/login/login.component.spec.ts b/src/pages/login/login.component.spec.ts new file mode 100644 index 0000000..6972cf6 --- /dev/null +++ b/src/pages/login/login.component.spec.ts @@ -0,0 +1,52 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; + +import { LoginComponent } from './login.component'; +import { CommonComponentsModule } from '../../components/common/common.module'; + +describe('LoginComponent', () => { + let component: LoginComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [LoginComponent], + imports: [TranslateModule.forRoot(), CommonComponentsModule, FormsModule, ReactiveFormsModule], + providers: [TranslateService, PageService, UserService, FormBuilder], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('getError', () => { + it('should return the error message', () => { + component.formGroup.controls['email'].markAsTouched(); // left the field without entering anything + component.formGroup.controls['email'].setErrors({ email: true }); // invalid email + + Object.keys(component.formGroup.controls['email'].errors ?? {}).forEach((key) => { + expect(component.getError(key)).toEqual(`global.errors.${key}`); + }); + }); + }); + + describe('login', () => { + it('should login', () => { + component.formGroup.controls['email'].setValue('exemple@domain.com'); + component.formGroup.controls['password'].setValue('password'); + component.login(); + expect(true).toBeTrue(); // TODO: add a test once the API is ready + }); + }); +}); diff --git a/src/pages/login/login.component.ts b/src/pages/login/login.component.ts new file mode 100644 index 0000000..9279fe3 --- /dev/null +++ b/src/pages/login/login.component.ts @@ -0,0 +1,74 @@ +import type { email } from '#types'; +import type { OutputErrorResponseDto } from '#types/api'; + +import { Component, Inject } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; + +import { getErrors } from '@directives'; +import { APIService, ApiError } from '@services/api.service'; +import { PageService } from '@services/page.service'; +import { SnackbarService } from '@services/snackbar.service'; +import { UserService } from '@services/user.service'; + +type LoginForm = typeof LOGIN_FORM_GROUP; +type LoginFormKeys = keyof LoginForm['controls']; +const LOGIN_FORM_GROUP = new FormGroup({ + email: new FormControl('' as email, { + nonNullable: true, + validators: [Validators.required, Validators.email], + }), + password: new FormControl('', { + nonNullable: true, + validators: [Validators.required], + }), +}); + +@Component({ + selector: 'sith-login', + templateUrl: './login.html', + styleUrls: ['./login.scss'], +}) +export class LoginComponent { + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(UserService) public readonly user: UserService, + @Inject(APIService) private readonly api: APIService, + @Inject(SnackbarService) private readonly snackbar: SnackbarService, + ) {} + + public readonly formGroup = LOGIN_FORM_GROUP; + + public login(): void { + this.user.login(this.formGroup.controls['email'].value, this.formGroup.controls['password'].value).subscribe({ + next: () => this.page.to(['users', `${this.user.logged_user_id}`, 'profile']), + error: (e: ApiError) => { + switch (e.error.statusCode) { + case 401: + this.formGroup.controls['password'].setErrors({ password_wrong: true }); + break; + + case 403: + setTimeout(() => { + this.page.to('verify'); + }, 500); + break; + + case 404: + this.formGroup.controls['email'].setErrors({ email_not_found: true }); + break; + + default: + this.snackbar.error(e.error.message, e.error.errors, e.error.statusCode); + } + }, + }); + } + + public errors(field: LoginFormKeys): string[] { + return getErrors(this.formGroup.controls[field]); + } + + public getError(field: string): string { + return `global.errors.${field}`; + } +} diff --git a/src/pages/login/login.html b/src/pages/login/login.html new file mode 100644 index 0000000..001632d --- /dev/null +++ b/src/pages/login/login.html @@ -0,0 +1,44 @@ +
+
+ +
+ Association des Étudiants + de l'université de technologie de Belfort-Montbéliard +
+
+ +
+ + +
+
+
+ + +
+
+ {{ getError(error) | translate }} +
+
+ +
+
+ + +
+
+ {{ getError(error) | translate }} +
+
+ + + {{ 'login.forgot_password' | translate }} + +
+ + +
+
diff --git a/src/pages/login/login.scss b/src/pages/login/login.scss new file mode 100644 index 0000000..cd5cfff --- /dev/null +++ b/src/pages/login/login.scss @@ -0,0 +1,137 @@ +main { + background-color: var(--gray3); + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + gap: 40px; + padding: 40px 20px 60px; + + > .warning { + font-family: Roboto, sans-serif; + background-color: var(--orange-hover); + color: var(--text-color-dark-bg); + border: 1px solid var(--orange); + padding: 10px; + width: 100%; + max-width: 400px; + border-radius: 5px; + text-align: center; + } + + > .header { + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + + > .logo { + width: 200px; + height: 130px; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + } + + > .text { + display: flex; + flex-direction: column; + color: var(--text-color-dark-bg); + font-family: Inter, sans-serif; + + > .title { + font-size: calc(25.5px * var(--font-size)); + } + + > .subtitle { + text-transform: uppercase; + font-size: calc(10px * var(--font-size)); + } + } + + &:hover > .text { + color: var(--dark-blue); + } + } + + > form { + width: 100%; + max-width: 400px; + display: flex; + flex-direction: column; + gap: 30px; + + > .form-head { + width: 100%; + } + + > .form-body { + display: flex; + flex-direction: column; + gap: 10px; + + > .global-link { + text-align: center; + } + + > .input-container { + width: 100%; + display: flex; + flex-direction: column; + gap: 5px; + + > .error { + font-family: Roboto, sans-serif; + color: var(--red); + font-size: calc(12px * var(--font-size)); + line-height: 14px; + margin-left: calc(32px + 5px); + display: flex; + flex-direction: column; + } + + > .input { + width: 100%; + display: flex; + gap: 5px; + + >.icon { + width: 16px; + height: 16px; + margin: 8px; + } + + > .custom-input { + width: 100%; + } + + > input { + font-family: Roboto, sans-serif; + font-weight: normal; + color: var(--text-color-dark-bg); + background-color: var(--gray4); + width: 100%; + border: none; + border-radius: 5px; + height: 32px; + padding: 5px 5px 5px 10px; + display: flex; + justify-content: center; + align-items: center; + + &::placeholder { + color: var(--text-color-dark-bg-placeholder); + font-size: calc(14px * var(--font-size)); + } + } + } + } + } + + > .form-button { + width: 100%; + } + } +} diff --git a/src/pages/pages.module.ts b/src/pages/pages.module.ts new file mode 100644 index 0000000..f364b9f --- /dev/null +++ b/src/pages/pages.module.ts @@ -0,0 +1,43 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; +import { NgHcaptchaModule } from 'ng-hcaptcha'; + +import { NotFoundComponent } from './404/not-found.component'; +import { ForgotPasswordComponent } from './forgot_password/forgot_password.component'; +import { HomeComponent } from './home/home.component'; +import { LoginComponent } from './login/login.component'; +import { RegisterComponent } from './register/register.component'; +import { UserPageModule } from './user/profile/profile.module'; +import { VerifyComponent } from './verify/verify.component'; +import { ComponentsModule } from '../components/components.module'; + +@NgModule({ + declarations: [ + NotFoundComponent, + HomeComponent, + LoginComponent, + RegisterComponent, + ForgotPasswordComponent, + VerifyComponent, + ], + exports: [ + NotFoundComponent, + HomeComponent, + LoginComponent, + RegisterComponent, + ForgotPasswordComponent, + VerifyComponent, + ], + imports: [ + FormsModule, + CommonModule, + TranslateModule, + NgHcaptchaModule, + UserPageModule, + ReactiveFormsModule, + ComponentsModule, + ], +}) +export class PagesModule {} diff --git a/src/pages/register/register.component.spec.ts b/src/pages/register/register.component.spec.ts new file mode 100644 index 0000000..2dea46c --- /dev/null +++ b/src/pages/register/register.component.spec.ts @@ -0,0 +1,66 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { NgHcaptchaModule, NgHcaptchaService } from 'ng-hcaptcha'; + +import { PageService } from '@services/page.service'; +import { UserService } from '@services/user.service'; +import { environment } from 'src/environments/environment.dev'; + +import { RegisterComponent } from './register.component'; +import { CommonComponentsModule } from '../../components/common/common.module'; + +describe('RegisterComponent', () => { + let component: RegisterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [RegisterComponent], + imports: [ + TranslateModule.forRoot(), + CommonComponentsModule, + FormsModule, + ReactiveFormsModule, + NgHcaptchaModule.forRoot({ siteKey: environment.HCAPTCHA_SITE_KEY }), + ], + providers: [PageService, TranslateService, UserService, FormBuilder, NgHcaptchaService], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('getError', () => { + it('should return the error message', () => { + component.formGroup.controls['email'].markAsTouched(); // left the field without entering anything + component.formGroup.controls['email'].setErrors({ email: true }); // invalid email + component.formGroup.controls['captcha'].markAsTouched(); // left the field without entering anything + component.formGroup.controls['captcha'].setErrors({ required: true }); // invalid captacha + + Object.keys(component.formGroup.controls['email'].errors ?? {}).forEach((key) => { + expect(component.getError(key.toString())).toEqual(`global.errors.${key}`); + }); + }); + }); + + describe('register', () => { + it('should register the user', () => { + component.formGroup.controls['email'].setValue('exemple@domain.com'); + component.formGroup.controls['password'].setValue('Password!0'); + component.formGroup.controls['password_confirm'].setValue('Password!0'); + component.formGroup.controls['first_name'].setValue('John'); + component.formGroup.controls['last_name'].setValue('Doe'); + component.formGroup.controls['birth_date'].setValue('01/01/2000'); + component.register(); // TODO: add a test once the API is ready + expect(true).toBeTrue(); + }); + }); +}); diff --git a/src/pages/register/register.component.ts b/src/pages/register/register.component.ts new file mode 100644 index 0000000..8a35822 --- /dev/null +++ b/src/pages/register/register.component.ts @@ -0,0 +1,117 @@ +import type { email } from '#types'; +import type { OutputErrorResponseDto, InputRegisterUserDto, OutputUserDto } from '#types/api'; + +import { Component, Inject } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; + +import { CustomValidators, getErrors } from '@directives'; +import { environment } from '@environments/environment'; +import { APIService, ApiError } from '@services/api.service'; +import { PageService } from '@services/page.service'; +import { SnackbarService } from '@services/snackbar.service'; + +type RegisterForm = typeof REGISTER_FORM_GROUP; +type RegisterFormKeys = keyof RegisterForm['controls']; +const REGISTER_FORM_GROUP = new FormGroup( + { + first_name: new FormControl('', { + nonNullable: true, + validators: [ + Validators.required, + Validators.minLength(environment.USERS.MIN_NAME_LENGTH), + Validators.maxLength(environment.USERS.MAX_NAME_LENGTH), + CustomValidators.nameValidator, + ], + }), + last_name: new FormControl('', { + nonNullable: true, + validators: [ + Validators.required, + Validators.minLength(environment.USERS.MIN_NAME_LENGTH), + Validators.maxLength(environment.USERS.MAX_NAME_LENGTH), + CustomValidators.nameValidator, + ], + }), + email: new FormControl('' as email, { + nonNullable: true, + validators: [Validators.required, Validators.email, CustomValidators.forbiddenEmailValidator('@utbm.fr')], + }), + birth_date: new FormControl('', { + nonNullable: true, + validators: [ + Validators.required, + CustomValidators.ageMinValidator(environment.USERS.MIN_AGE), + CustomValidators.ageMaxValidator(environment.USERS.MAX_AGE), + CustomValidators.notInFutureValidator, + ], + }), + password: new FormControl('', { + nonNullable: true, + validators: [ + Validators.required, + Validators.minLength(8), + CustomValidators.hasOneDigit, + CustomValidators.hasOneSpecialCharacter, + CustomValidators.hasOneUppercase, + CustomValidators.hasOneLowercase, + CustomValidators.hasNoDuplicateCharacters, + ], + }), + password_confirm: new FormControl('', { nonNullable: true, validators: [Validators.required] }), + captcha: new FormControl('', { nonNullable: true, validators: Validators.required }), + }, + { validators: CustomValidators.passwordsMatchValidator() }, +); + +@Component({ + selector: 'sith-register', + templateUrl: './register.html', + styleUrls: ['./register.scss'], +}) +export class RegisterComponent { + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(APIService) private readonly api: APIService, + @Inject(SnackbarService) private readonly snackbar: SnackbarService, + ) {} + + public readonly formGroup = REGISTER_FORM_GROUP; + public readonly MIN_NAME = environment.USERS.MIN_NAME_LENGTH; + public readonly MAX_NAME = environment.USERS.MAX_NAME_LENGTH; + public readonly MIN_AGE = environment.USERS.MIN_AGE; + public readonly MAX_AGE = environment.USERS.MAX_AGE; + public readonly MIN_PASSWORD = environment.USERS.MIN_PASSWORD_LENGTH; + + public errors(field: RegisterFormKeys): string[] { + if ('password_confirm' === field) + return [...getErrors(this.formGroup.controls[field]), ...getErrors(this.formGroup)]; + + return getErrors(this.formGroup.controls[field]); + } + + public getError(key: string): string { + return `global.errors.${key}`; + } + + public register(): void { + this.api + .post('/auth/register', { + first_name: this.formGroup.controls.first_name.value, + last_name: this.formGroup.controls.last_name.value, + email: this.formGroup.controls.email.value, + birth_date: new Date(this.formGroup.controls.birth_date.value), + password: this.formGroup.controls.password.value, + }) + .subscribe({ + next: (user) => { + setTimeout(() => { + this.page.to('verify', { state: { email: user.email } }); + }, 1000); + }, + error: (err: ApiError) => { + console.error(err); + this.snackbar.error(err.error.message, err.error.errors, err.error.statusCode); + }, + }); + } +} diff --git a/src/pages/register/register.html b/src/pages/register/register.html new file mode 100644 index 0000000..33f0297 --- /dev/null +++ b/src/pages/register/register.html @@ -0,0 +1,83 @@ +
+
+ +
+ Association des Étudiants + de l'université de technologie de Belfort-Montbéliard +
+
+ +
+ + +
+
+
+ +
+
+ {{ getError(error) | translate: { min: MIN_NAME, max: MAX_NAME } }} +
+
+ +
+
+ +
+
+ {{ getError(error) | translate: { min: MIN_NAME, max: MAX_NAME } }} +
+
+ +
+
+ + +
+ {{ 'register.date_birth_no_modif' | translate }} +
+ {{ getError(error) | translate: { min: MIN_AGE, max: MAX_AGE } }} +
+
+ +
+
+ + +
+
+ {{ getError(error) | translate }} +
+
+ +
+
+ + +
+ {{ 'register.min_password' | translate }} +
+ {{ getError(error) | translate: { min: MIN_PASSWORD } }} +
+
+ +
+
+ + +
+ {{ 'register.confirm_password' | translate }} +
+ {{ getError(error) | translate }} +
+
+
+ + + + +
+
diff --git a/src/pages/register/register.scss b/src/pages/register/register.scss new file mode 100644 index 0000000..5f94eb6 --- /dev/null +++ b/src/pages/register/register.scss @@ -0,0 +1,149 @@ +main { + background-color: var(--gray3); + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + gap: 40px; + padding: 40px 20px 60px; + + > .warning { + font-family: Roboto, sans-serif; + background-color: var(--orange-hover); + color: var(--text-color-dark-bg); + border: 1px solid var(--orange); + padding: 10px; + width: 100%; + max-width: 400px; + border-radius: 5px; + text-align: center; + } + + > .header { + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + + > .logo { + width: 200px; + height: 130px; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + } + + > .text { + display: flex; + flex-direction: column; + color: var(--text-color-dark-bg); + font-family: Inter, sans-serif; + + > .title { + font-size: calc(25.5px * var(--font-size)); + } + + > .subtitle { + text-transform: uppercase; + font-size: calc(10px * var(--font-size)); + } + } + + &:hover > .text { + color: var(--dark-blue); + } + } + + > form { + width: 100%; + max-width: 400px; + display: flex; + flex-direction: column; + gap: 30px; + + > .form-head { + width: 100%; + } + + > .form-body { + display: flex; + flex-direction: column; + gap: 10px; + + > .input-container { + width: 100%; + display: flex; + flex-direction: column; + gap: 5px; + + > .error, + > .info { + font-family: Roboto, sans-serif; + font-size: calc(12px * var(--font-size)); + line-height: 14px; + margin-left: calc(32px + 5px); + display: flex; + flex-direction: column; + + &.no-margin { + margin-left: 0; + } + } + + > .error { + color: var(--red); + } + + > .info { + color: var(--text-color-dark-bg); + } + + > .input { + width: 100%; + display: flex; + gap: 5px; + + >.icon { + width: 16px; + height: 16px; + margin: 8px; + } + + > .custom-input { + width: 100%; + } + + > input { + font-family: Roboto, sans-serif; + font-weight: normal; + color: var(--text-color-dark-bg); + background-color: var(--gray4); + width: 100%; + border: none; + border-radius: 5px; + height: 32px; + padding: 5px 5px 5px 10px; + display: flex; + justify-content: flex-start; + align-items: center; + + &::placeholder { + color: var(--text-color-dark-bg-placeholder); + font-size: calc(14px * var(--font-size)); + } + } + } + } + } + + > .form-captcha { + margin: 0 auto; + } + + > .form-button { + width: 100%; + } + } +} diff --git a/src/pages/user/profile/desktop/profile-desktop.component.ts b/src/pages/user/profile/desktop/profile-desktop.component.ts new file mode 100644 index 0000000..66f0a84 --- /dev/null +++ b/src/pages/user/profile/desktop/profile-desktop.component.ts @@ -0,0 +1,12 @@ +import { Component, Inject } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-user-profile-desktop', + templateUrl: './profile-desktop.html', + styleUrls: ['./profile-desktop.scss'], +}) +export class UserProfileDesktopComponent { + public constructor(@Inject(PageService) public readonly page: PageService) {} +} diff --git a/src/pages/user/profile/desktop/profile-desktop.html b/src/pages/user/profile/desktop/profile-desktop.html new file mode 100644 index 0000000..031483d --- /dev/null +++ b/src/pages/user/profile/desktop/profile-desktop.html @@ -0,0 +1 @@ + diff --git a/src/pages/user/profile/desktop/profile-desktop.scss b/src/pages/user/profile/desktop/profile-desktop.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/user/profile/mobile/profile-mobile.component.ts b/src/pages/user/profile/mobile/profile-mobile.component.ts new file mode 100644 index 0000000..87d2882 --- /dev/null +++ b/src/pages/user/profile/mobile/profile-mobile.component.ts @@ -0,0 +1,31 @@ +import type { base64, imageURL } from '#types'; +import type { OutputUserDto } from '#types/api'; + +import { Component, EventEmitter, Inject, Input, Output } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-user-profile-mobile', + templateUrl: './profile-mobile.html', + styleUrls: ['./profile-mobile.scss'], +}) +export class UserProfileMobileComponent { + public constructor(@Inject(PageService) public readonly page: PageService) {} + + @Input() public user?: OutputUserDto; + @Input() public userPicture?: base64 | imageURL; + @Input() public userBanner?: base64 | imageURL; + + @Input() public userCanEdit = false; + @Input() public userCanReadPrivate = false; + + @Input() public self = false; + + @Output() public openModal = new EventEmitter<'infos' | 'banner' | 'picture'>(); + + public currentTab: 'about' | 'contact' = 'about'; + + public banned = true; + public suspended = true; +} diff --git a/src/pages/user/profile/mobile/profile-mobile.html b/src/pages/user/profile/mobile/profile-mobile.html new file mode 100644 index 0000000..e2b55c1 --- /dev/null +++ b/src/pages/user/profile/mobile/profile-mobile.html @@ -0,0 +1,112 @@ +
+
+ + +
+
+ +
+ +
+ +
+ +
+
+ {{ user?.full_name }} +
+
{{ user?.nickname }} ‐
+
{{ 'profile.age' | translate: { age: user?.age } }}
+
+
+ +
+ +
+
+
+ + +
+ +
+ +
+ +
+
+ {{ 'profile.birth_date' | translate }} + {{ user?.birth_date | date: 'dd/MM/yyyy' }} +
+ +
+ {{ 'profile.cursus_utbm' | translate }} + NYI +
+
+ {{ 'profile.joined_the_site' | translate }} + {{ user?.created | date: 'dd/MM/yyyy' }} +
+
+ {{ 'profile.gender' | translate }} + {{ user?.gender ?? '-' }} +
+ +
+ {{ 'profile.specialty' | translate }} + NYI +
+
+ {{ 'profile.last_seen' | translate }} + {{ (user?.last_seen | date: 'dd/MM/yyyy') ?? ('profile.never_seen' | translate) }} +
+
+ {{ 'profile.pronouns' | translate }} + {{ user?.pronouns ?? '-' }} +
+
+ {{ 'profile.promotion' | translate }} + {{ user?.promotion ?? '-' }} +
+ +
+ {{ 'profile.subscription' | translate }} + NYI +
+
+ + +
+
+ {{ 'profile.email' | translate }} + {{ user?.email ?? '-' }} +
+
+ {{ 'profile.secondary_email' | translate }} + {{ user?.secondary_email ?? '-' }} +
+
+ {{ 'profile.phone' | translate }} + {{ user?.phone ?? '-' }} +
+
+ {{ 'profile.parents_phone' | translate }} + {{ user?.parents_phone ?? '-' }} +
+
+
+
+
+
+
diff --git a/src/pages/user/profile/mobile/profile-mobile.scss b/src/pages/user/profile/mobile/profile-mobile.scss new file mode 100644 index 0000000..8017044 --- /dev/null +++ b/src/pages/user/profile/mobile/profile-mobile.scss @@ -0,0 +1,286 @@ +.content { + display: flex; + flex-direction: column; + gap: 5px; + padding: 5px; + min-height: calc(100vh - 110px); + + >.profile { + display: flex; + flex-direction: column; + + >.banner { + height: 52px; + position: relative; + + >.suspended, + >.banned { + font-family: 'Roboto', sans-serif; + font-size: 12px; + text-transform: uppercase; + height: 20px; + padding: 0 10px; + border-radius: 5px; + display: flex; + align-items: center; + justify-content: center; + + position: absolute; + top: 0; + right: 0; + + &.rtl { + right: unset; + left: 0; + } + } + + >.suspended { + background-color: var(--orange); + color: var(--text-color); + } + + >.banned { + background-color: var(--red); + color: var(--text-color-dark-bg); + } + + >.pencil { + height: 24px; + width: 24px; + display: flex; + justify-content: center; + align-items: center; + position: absolute; + + padding: 4px; + border-radius: 50%; + + bottom: 5px; + right: 0; + + fill: var(--text-color-dark-bg); + background-color: var(--darkened); + + cursor: pointer; + } + + &.has-banner { + height: auto; + + >.banner-image { + width: 100%; + border-radius: 5px 5px 0 0; + margin-bottom: -4px; + } + + >.pencil { + right: 5px; + top: 5px; + bottom: unset; + + cursor: pointer; + } + + >.banned, + >.suspended { + top: 5px; + left: 5px; + right: unset; + } + } + } + + >.infos { + display: flex; + flex-direction: column; + position: relative; + gap: 10px; + background-color: var(--background-color-lighter); + padding: 10px; + border-radius: 5px; + min-height: 100%; + + >.pictures { + position: absolute; + top: calc(95px / -2); + + width: 95px; + height: 95px; + + border: 5px solid var(--background-color-lighter); + border-radius: 50%; + background-color: var(--background-color-lighter); + + >.picture-hover { + display: none; + + position: absolute; + top: 0; + + background-color: rgba(0, 0, 0, 0.5); + border-radius: 50%; + + width: 85px; + height: 85px; + + cursor: pointer; + + >.pencil { + height: 25px; + width: 25px; + fill: var(--text-color-dark-bg); + } + } + + >.picture-hover:hover, + >.picture:hover~.picture-hover { + display: flex; + align-items: center; + justify-content: center; + } + + &.rtl { + left: unset; + right: 10px; + } + + >.promotion { + position: absolute; + bottom: -5px; + right: -5px; + + width: 40px; + height: 40px; + + background-color: var(--background-color-lighter); + border-radius: 50%; + + &.rtl { + right: unset; + left: -5px; + } + } + } + + >.main { + min-height: 42px; + margin-left: 105px; + font-family: Roboto, sans-serif; + + display: flex; + flex-direction: row; + color: var(--text-color-dynamic); + + &.rtl { + margin-left: unset; + margin-right: 105px; + } + + >div { + display: flex; + flex-direction: column; + width: 100%; + + >.name { + text-transform: capitalize; + font-weight: bold; + } + + >.subname { + font-weight: 300; + display: flex; + + >.nickname { + margin-right: 5px; + } + } + } + + >.flag { + fill: var(--red); + height: 20px; + width: 20px; + } + } + + >.tab { + width: 100%; + padding: 5px 0; + + >.header { + display: flex; + gap: 10px; + + >.tabs { + width: 100%; + + >.link { + border: none; + background-color: transparent; + + font-family: Roboto, sans-serif; + font-size: 12px; + color: var(--text-color-dynamic); + + cursor: pointer; + + &.shown { + cursor: auto; + border-bottom: 1px solid var(--text-color-dynamic); + } + } + + border-bottom: 1px solid var(--text-color-dynamic); + } + + >.pencil { + height: 20px; + width: 20px; + fill: var(--text-color-dynamic); + + cursor: pointer; + } + } + + >.body { + display: flex; + flex-direction: row; + + >.details { + visibility: hidden; + width: 100%; + display: flex; + flex-wrap: wrap; + display: none; + color: var(--text-color-dynamic); + + &.shown { + visibility: visible; + display: flex; + } + + >.column { + display: flex; + flex-direction: column; + font-family: Roboto, sans-serif; + font-size: 10px; + text-transform: uppercase; + padding-top: 10px; + width: calc(100% / 3); + height: 35px; + + >.title { + font-weight: bold; + } + } + } + } + } + } + + >.banner.has-banner~.infos { + border-radius: 0 0 5px 5px; + } + } +} diff --git a/src/pages/user/profile/modals/banner-modal/banner-edit-modal.component.ts b/src/pages/user/profile/modals/banner-modal/banner-edit-modal.component.ts new file mode 100644 index 0000000..cc0b986 --- /dev/null +++ b/src/pages/user/profile/modals/banner-modal/banner-edit-modal.component.ts @@ -0,0 +1,122 @@ +import type { base64, imageURL } from '#types'; +import type { ImageCropperResult } from 'types'; + +import { OnInit, ViewChild, ElementRef, Component, Inject, Output, EventEmitter, Input } from '@angular/core'; + +import { ImageCropperComponent } from '@components/common/image_cropper/image-cropper.component'; +import { SnackbarService } from '@services/snackbar.service'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-user-profile-banner-edit-modal', + templateUrl: './banner-edit-modal.html', + styleUrls: ['./banner-edit-modal.scss'], +}) +export class UserProfileBannerEditModalComponent implements OnInit { + public constructor( + @Inject(UserService) private readonly userService: UserService, + @Inject(SnackbarService) private readonly snackbarService: SnackbarService, + ) { + if (this.userBannerId) + this.userService.userFileData(this.userBannerId).subscribe({ + next: (data) => { + console.warn(data); + }, + error: (err) => { + console.error(err); + }, + }); + } + + @Input() public username?: string; + @Input() public userId?: number; + @Input() public userBanner?: base64 | imageURL; + @Input() public userBannerId?: number; + @Input() public userCanEdit = false; + @Input() public userCanReadPrivate = false; + + @Input() public self = false; + + @Output() public bannerUpdated = new EventEmitter(); + + @ViewChild('banner', { static: true }) public modal!: ElementRef; + @ViewChild(ImageCropperComponent, { static: false }) public cropper!: ImageCropperComponent; + + public bannerUncropped?: base64; + public bannerCropped?: ImageCropperResult; + + public readonly options: Cropper.Options = { + aspectRatio: 3, + rotatable: true, + zoomable: true, + scalable: true, + }; + + public timeLeft?: Date; + public pageUserId?: number; + + public ngOnInit(): void { + this.modal.nativeElement.addEventListener('click', (e) => { + const dimensions = this.modal.nativeElement.getBoundingClientRect(); + if (!dimensions) return; + + if ( + e.clientX < dimensions.left || + e.clientX > dimensions.right || + e.clientY < dimensions.top || + e.clientY > dimensions.bottom + ) + this.close(); + }); + } + + public open() { + // Only the user can update his picture (or an admin) + if (!this.self && !this.userCanEdit) return; + + this.modal.nativeElement.showModal(); + } + + public close() { + this.modal.nativeElement.close(); + } + + public updateUncroppedBanner(file: base64) { + this.bannerUncropped = file; + } + + public async updateCroppedBanner(event: unknown) { + this.bannerCropped = event as ImageCropperResult; + if (!this.bannerCropped.dataUrl) return; + + const dataUrl: base64 = this.bannerCropped.dataUrl; + const res: Response = await fetch(dataUrl); + const blob: Blob = await res.blob(); + const file = new File([blob], 'profile_picture.png', { type: 'image/png' }); + + const formData = new FormData(); + formData.append('file', file, file.name); + + this.userService.updateUserBanner(this.userId ?? 0, formData).subscribe({ + next: (data) => { + console.warn(data); + this.bannerUpdated.emit(dataUrl); + }, + error: (err) => { + console.error(err); + }, + }); + } + + public deleteCurrentBanner() { + this.userService.deleteUserBanner(this.userId ?? 0).subscribe({ + next: (data) => { + this.bannerUpdated.emit(); + this.snackbarService.success(data.message, 'Success'); + }, + error: (err) => { + console.error(err); + }, + }); + } +} diff --git a/src/pages/user/profile/modals/banner-modal/banner-edit-modal.html b/src/pages/user/profile/modals/banner-modal/banner-edit-modal.html new file mode 100644 index 0000000..2db7f2c --- /dev/null +++ b/src/pages/user/profile/modals/banner-modal/banner-edit-modal.html @@ -0,0 +1,38 @@ + diff --git a/src/pages/user/profile/modals/banner-modal/banner-edit-modal.scss b/src/pages/user/profile/modals/banner-modal/banner-edit-modal.scss new file mode 100644 index 0000000..0601b37 --- /dev/null +++ b/src/pages/user/profile/modals/banner-modal/banner-edit-modal.scss @@ -0,0 +1,35 @@ +.banner-dialog { + width: 90%; + max-width: 500px; + + position: relative; + border: none; + border-radius: 5px; + padding: 0 10px 10px; + background-color: var(--background-color); + + >form { + display: flex; + flex-direction: column; + gap: 10px; + + >.cropper { + max-height: 600px; + } + + >.warning { + color: var(--red); + font-family: 'Roboto', sans-serif; + text-align: center; + } + } + + >.close { + position: absolute; + width: 16px; + height: 16px; + top: 10px; + right: 10px; + fill: var(--text-color-dynamic); + } +} diff --git a/src/pages/user/profile/modals/infos-modal/infos-edit-modal.component.ts b/src/pages/user/profile/modals/infos-modal/infos-edit-modal.component.ts new file mode 100644 index 0000000..1aa05dc --- /dev/null +++ b/src/pages/user/profile/modals/infos-modal/infos-edit-modal.component.ts @@ -0,0 +1,202 @@ +import { Component, ElementRef, Inject, Input, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; + +import { CustomValidators } from '@directives'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-user-profile-infos-edit-modal', + templateUrl: './infos-edit-modal.html', + styleUrls: ['./infos-edit-modal.scss'], +}) +export class UserProfileInfosEditModalComponent implements OnInit { + @ViewChild('modal', { static: true }) public modal!: ElementRef; + @Input() public username = ''; + + private userId = 0; + + public readonly infosForm: FormGroup = this.fb.group({ + last_name: [null, [Validators.required, Validators.minLength(2), CustomValidators.nameValidator]], + first_name: [null, [Validators.required, Validators.minLength(2), CustomValidators.nameValidator]], + nickname: [null, []], + email: [null, [Validators.required, Validators.email, CustomValidators.forbiddenEmailValidator('@utbm.fr')]], + birthday: [ + null, + [ + Validators.required, + CustomValidators.ageMinValidator, + CustomValidators.ageMaxValidator, + CustomValidators.notInFutureValidator, + ], + ], + parent_contact: [ + null, + // [CustomValidators.requiredIfBelow(18, this.user.birth_date ? this.user.birthday.elapsedYears() : 0)], + ], + secondary_email: [null, [Validators.email]], + phone: [null, []], + gender: [null, []], + pronouns: [null, []], + cursus: [null, []], + specialty: [null, []], + promotion: [null, []], + }); + + public visibility: { [key: string]: boolean } = {}; + + public minPromotion = 1; + public maxPromotion = -1; + + public constructor( + @Inject(FormBuilder) private readonly fb: FormBuilder, + @Inject(UserService) public readonly user: UserService, + ) { + // this.activeRoute.params.subscribe((params) => { + // this.userId = parseInt(params['id'] as string, 10); // FIXME params['id'] might be undefined + // this.fetchUserData(); + // this.fetchUserVisibility(); + // if (this.isSelf()) { + // this.infosForm.get('first_name')?.disable(); + // this.infosForm.get('last_name')?.disable(); + // this.infosForm.get('birthday')?.disable(); + // } + // }); + } + + public ngOnInit(): void { + this.modal.nativeElement.addEventListener('click', (e) => { + const dimensions = this.modal.nativeElement.getBoundingClientRect(); + if (!dimensions) return; + + if ( + e.clientX < dimensions.left || + e.clientX > dimensions.right || + e.clientY < dimensions.top || + e.clientY > dimensions.bottom + ) + this.close(); + }); + + this.fetchLastPromotion(); + } + + public fetchUserData() { + // this.apollo + // .query<{ userPrivate: PrivateUser }>({ + // query: gql` + // query ($user_id: Int!) { + // userPrivate(id: $user_id) { + // first_name + // last_name + // nickname + // birthday + // email + // secondary_email + // phone + // gender + // pronouns + // cursus + // specialty + // promotion { + // number + // } + // } + // } + // `, + // variables: { + // user_id: this.userId, + // }, + // fetchPolicy: 'cache-first', + // errorPolicy: 'all', + // }) + // .subscribe(({ data, error }) => { + // if (!data || error) return; + // this.infosForm.patchValue({ + // ...data.userPrivate, + // birthday: data.userPrivate.birthday.toString().split('T')[0], + // promotion: data.userPrivate.promotion?.number, + // }); + // }); + } + + public fetchUserVisibility() { + // this.apollo + // .query<{ userVisibility: UserVisibility }>({ + // query: gql` + // query ($user_id: Int!) { + // userVisibility(id: $user_id) { + // birthday + // cursus + // email + // gender + // parent_contact + // phone + // promotion + // pronouns + // secondary_email + // specialty + // } + // } + // `, + // variables: { + // user_id: this.userId, + // }, + // fetchPolicy: 'cache-first', + // errorPolicy: 'all', + // }) + // .subscribe(({ data, errors }) => { + // if (!data || errors) return; + // Object.merge(this.visibility, data.userVisibility); + // }); + } + + public fetchLastPromotion() { + // this.apollo + // .query<{ latestPromotion: Promotion }>({ + // query: gql` + // query { + // latestPromotion { + // number + // } + // } + // `, + // fetchPolicy: 'cache-first', + // errorPolicy: 'all', + // }) + // .subscribe(({ data, error }) => { + // if (!data || error) return; + // this.maxPromotion = data['latestPromotion'].number; + // }); + } + + public updatePromotion(event: Event) { + const value = parseInt((event.target as HTMLInputElement).value, 10); + if (value < this.minPromotion) this.infosForm.controls['promotion'].setValue(this.minPromotion); + if (value > this.maxPromotion) this.infosForm.controls['promotion'].setValue(this.maxPromotion); + } + + public get promotion(): number { + return this.infosForm.get('promotion')?.value as number; + } + + public isSelf() { + return this.userId === this.user.logged_user_id; + } + + public open() { + this.modal.nativeElement.showModal(); + } + + public close() { + this.modal.nativeElement.close(); + } + + /** + * Cancel the changes and close the modal + */ + public cancel() { + this.fetchUserData(); + this.fetchUserVisibility(); + this.close(); + } +} diff --git a/src/pages/user/profile/modals/infos-modal/infos-edit-modal.html b/src/pages/user/profile/modals/infos-modal/infos-edit-modal.html new file mode 100644 index 0000000..7dc345a --- /dev/null +++ b/src/pages/user/profile/modals/infos-modal/infos-edit-modal.html @@ -0,0 +1,148 @@ + + +

{{ 'profile.identity_info' | translate }}

+ +
+ +
+
+
+
{{ 'profile.first_name' | translate }}
+
+ +
+
+
+
{{ 'profile.last_name' | translate }}
+
+ +
+
+
+
+ +
+
+
+
{{ 'profile.nickname' | translate }}
+
+ +
+
+
+
{{ 'profile.birthday' | translate }}
+
+ + +
+
+
+
+ + +
+
+
+
{{ 'profile.email' | translate }}
+
+ + +
+
+
+
{{ 'profile.secondary_email' | translate }}
+
+ + +
+
+
+
+ +
+
+
+
{{ 'profile.phone' | translate }}
+
+ + +
+
+
+
+ +
+
+
+
{{ 'profile.gender' | translate }}
+
+ + +
+
+
+
{{ 'profile.pronouns' | translate }}
+
+ + +
+
+
+
+ +
+
+
+
{{ 'profile.cursus_utbm' | translate }}
+
+ + +
+
+
+
{{ 'profile.specialty' | translate }}
+
+ + +
+
+
+
+ +
+
+
+
{{ 'profile.promotion' | translate }}
+
+ + +
+
+ +
+
+ +
+ + + +
+ + +
+ +
diff --git a/src/pages/user/profile/modals/infos-modal/infos-edit-modal.scss b/src/pages/user/profile/modals/infos-modal/infos-edit-modal.scss new file mode 100644 index 0000000..7ef1996 --- /dev/null +++ b/src/pages/user/profile/modals/infos-modal/infos-edit-modal.scss @@ -0,0 +1,106 @@ +.infos-text { + font-family: 'Inter', sans-serif; + font-style: italic; + font-weight: 400; + font-size: 12px; + text-align: justify; + color: var(--text-color-dynamic); +} + +.infos-dialog { + width: 90%; + max-width: 500px; + + position: relative; + border: none; + border-radius: 5px; + padding: 0 10px 10px; + background-color: var(--background-color); + + > form { + display: flex; + flex-direction: column; + gap: 10px; + + > .field { + display: flex; + flex-direction: column; + gap: 5px; + + > .inputs { + display: flex; + flex-direction: row; + gap: 10px; + + > .logo { + min-width: 50px; + height: 50px; + margin-top: 10px; + } + + > .input-container { + display: flex; + flex-direction: column; + width: 100%; + gap: 5px; + + > .subtitle { + font-family: 'Roboto', sans-serif; + font-style: normal; + font-weight: 700; + font-size: 14px; + text-transform: uppercase; + color: var(--text-color-dynamic); + } + + > .input { + display: flex; + flex-direction: row; + width: 100%; + align-items: center; + gap: 5px; + min-height: 24px; + + .icon { + width: 18px; + height: 18px; + fill: var(--text-color-dynamic); + cursor: pointer; + } + + input { + width: 100%; + height: 30px; + border: none; + border-radius: 5px; + + font-family: 'Roboto', sans-serif; + font-style: normal; + font-weight: 400; + font-size: 14px; + padding-left: 5px; + background-color: var(--background-color-lighter); + color: var(--text-color-dynamic); + + &:disabled { + background-color: var(--background-color-lighter); + color: var(--text-disabled-color-dynamic); + } + } + } + } + } + } + } + + > .buttons { + display: flex; + flex-direction: row; + gap: 10px; + margin-top: 30px; + + > .button { + width: 100%; + } + } +} diff --git a/src/pages/user/profile/modals/picture-modal/picture-edit-modal.component.ts b/src/pages/user/profile/modals/picture-modal/picture-edit-modal.component.ts new file mode 100644 index 0000000..b399282 --- /dev/null +++ b/src/pages/user/profile/modals/picture-modal/picture-edit-modal.component.ts @@ -0,0 +1,122 @@ +import type { base64, imageURL } from '#types'; +import type { ImageCropperResult } from 'types'; + +import { OnInit, ViewChild, ElementRef, Component, Inject, Output, EventEmitter, Input } from '@angular/core'; + +import { ImageCropperComponent } from '@components/common/image_cropper/image-cropper.component'; +import { SnackbarService } from '@services/snackbar.service'; +import { UserService } from '@services/user.service'; + +@Component({ + selector: 'sith-user-profile-picture-edit-modal', + templateUrl: './picture-edit-modal.html', + styleUrls: ['./picture-edit-modal.scss'], +}) +export class UserProfilePictureEditModalComponent implements OnInit { + public constructor( + @Inject(UserService) private readonly userService: UserService, + @Inject(SnackbarService) private readonly snackbarService: SnackbarService, + ) { + if (this.userPictureId) + this.userService.userFileData(this.userPictureId).subscribe({ + next: (data) => { + console.warn(data); + }, + error: (err) => { + console.error(err); + }, + }); + } + + @Input() public username?: string; + @Input() public userId?: number; + @Input() public userPicture?: base64 | imageURL; + @Input() public userPictureId?: number; + @Input() public userCanEdit = false; + @Input() public userCanReadPrivate = false; + + @Input() public self = false; + + @Output() public pictureUpdated = new EventEmitter(); + + @ViewChild('picture', { static: true }) public modal!: ElementRef; + @ViewChild(ImageCropperComponent, { static: false }) public cropper!: ImageCropperComponent; + + public pictureUncropped?: base64; + public pictureCropped?: ImageCropperResult; + + public readonly options: Cropper.Options = { + aspectRatio: 1, + rotatable: true, + zoomable: true, + scalable: true, + }; + + public timeLeft?: Date; + public pageUserId?: number; + + public ngOnInit(): void { + this.modal.nativeElement.addEventListener('click', (e) => { + const dimensions = this.modal.nativeElement.getBoundingClientRect(); + if (!dimensions) return; + + if ( + e.clientX < dimensions.left || + e.clientX > dimensions.right || + e.clientY < dimensions.top || + e.clientY > dimensions.bottom + ) + this.close(); + }); + } + + public open() { + // Only the user can update his picture (or an admin) + if (!this.self && !this.userCanEdit) return; + + this.modal.nativeElement.showModal(); + } + + public close() { + this.modal.nativeElement.close(); + } + + public updateUncroppedPicture(file: base64) { + this.pictureUncropped = file; + } + + public async updateCroppedPicture(event: unknown) { + this.pictureCropped = event as ImageCropperResult; + if (!this.pictureCropped.dataUrl) return; + + const dataUrl: base64 = this.pictureCropped.dataUrl; + const res: Response = await fetch(dataUrl); + const blob: Blob = await res.blob(); + const file = new File([blob], 'profile_picture.png', { type: 'image/png' }); + + const formData = new FormData(); + formData.append('file', file, file.name); + + this.userService.updateUserPicture(this.userId ?? 0, formData).subscribe({ + next: (data) => { + console.warn(data); + this.pictureUpdated.emit(dataUrl); + }, + error: (err) => { + console.error(err); + }, + }); + } + + public deleteCurrentPicture() { + this.userService.deleteUserPicture(this.userId ?? 0).subscribe({ + next: (data) => { + this.pictureUpdated.emit(); + this.snackbarService.success(data.message, 'Success'); + }, + error: (err) => { + console.error(err); + }, + }); + } +} diff --git a/src/pages/user/profile/modals/picture-modal/picture-edit-modal.html b/src/pages/user/profile/modals/picture-modal/picture-edit-modal.html new file mode 100644 index 0000000..df7c74f --- /dev/null +++ b/src/pages/user/profile/modals/picture-modal/picture-edit-modal.html @@ -0,0 +1,38 @@ + + + +
+ + {{ 'profile.picture_too_recent' | translate: { date: timeLeft | date: 'dd/MM/yyyy HH:mm:ss' } }} + + + + + + + + + + +
diff --git a/src/pages/user/profile/modals/picture-modal/picture-edit-modal.scss b/src/pages/user/profile/modals/picture-modal/picture-edit-modal.scss new file mode 100644 index 0000000..de23243 --- /dev/null +++ b/src/pages/user/profile/modals/picture-modal/picture-edit-modal.scss @@ -0,0 +1,35 @@ +.picture-dialog { + width: 90%; + max-width: 500px; + + position: relative; + border: none; + border-radius: 5px; + padding: 0 10px 10px; + background-color: var(--background-color); + + >form { + display: flex; + flex-direction: column; + gap: 10px; + + >.cropper { + max-height: 600px; + } + + >.warning { + color: var(--red); + font-family: 'Roboto', sans-serif; + text-align: center; + } + } + + >.close { + position: absolute; + width: 16px; + height: 16px; + top: 10px; + right: 10px; + fill: var(--text-color-dynamic); + } +} diff --git a/src/pages/user/profile/profile.component.ts b/src/pages/user/profile/profile.component.ts new file mode 100644 index 0000000..cf90e9b --- /dev/null +++ b/src/pages/user/profile/profile.component.ts @@ -0,0 +1,106 @@ +import type { base64, imageURL } from '#types'; +import type { OutputUserDto } from '#types/api'; + +import { Component, Inject, ViewChild } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { PageService } from '@services/page.service'; +import { PermissionService } from '@services/permissions.service'; +import { UserService } from '@services/user.service'; + +import { UserProfileBannerEditModalComponent } from './modals/banner-modal/banner-edit-modal.component'; +import { UserProfileInfosEditModalComponent } from './modals/infos-modal/infos-edit-modal.component'; +import { UserProfilePictureEditModalComponent } from './modals/picture-modal/picture-edit-modal.component'; + +@Component({ + selector: 'sith-user-profile', + templateUrl: './profile.html', + styleUrls: ['./profile.scss'], +}) +export class UserProfileComponent { + public constructor( + @Inject(PageService) public readonly page: PageService, + @Inject(UserService) public readonly userService: UserService, + @Inject(ActivatedRoute) private readonly activeRoute: ActivatedRoute, + @Inject(PermissionService) public readonly permsService: PermissionService, + ) { + this.activeRoute.params.subscribe((params) => { + const { id } = params; + this.pageUserId = parseInt(id as string, 10); + + this.permsService + .hasPermissions(this.userService.logged_user_id, ['CAN_EDIT_USER', 'CAN_READ_USER_PRIVATE']) + .subscribe({ + next: (perms) => { + this.userCanEdit = perms.CAN_EDIT_USER; + this.userCanReadPrivate = perms.CAN_READ_USER_PRIVATE; + + this.userService.user(this.pageUserId, perms.CAN_READ_USER_PRIVATE).subscribe({ + next: (user) => { + this.user = user; + }, + error: (err) => { + console.error(err); + }, + }); + + this.userService.userPicture(this.pageUserId).subscribe({ + next: (picture) => { + this.userPicture = picture; + }, + error: (err) => { + console.error(err); + }, + }); + + this.userService.userBanner(this.pageUserId).subscribe({ + next: (banner) => { + this.userBanner = banner; + }, + error: (err) => { + console.error(err); + }, + }); + }, + error: () => ({}), // silently fail (default values are false) + }); + }); + } + + @ViewChild('infosModal') public infosModal!: UserProfileInfosEditModalComponent; + @ViewChild('bannerModal') public bannerModal!: UserProfileBannerEditModalComponent; + @ViewChild('pictureModal') public pictureModal!: UserProfilePictureEditModalComponent; + + openModal(modal: 'infos' | 'banner' | 'picture'): void { + switch (modal) { + case 'infos': + this.infosModal.open(); + break; + case 'banner': + this.bannerModal.open(); + break; + case 'picture': + this.pictureModal.open(); + break; + } + } + + private pageUserId = 0; + + public user?: OutputUserDto; + public userPicture?: base64 | imageURL; + public userBanner?: base64 | imageURL; + + public userCanEdit = false; + public userCanReadPrivate = false; + + public currentTab: 'about' | 'contact' = 'about'; + + public canEditPage(): boolean { + return this.isOwner() || this.userCanEdit; + } + + public isOwner(): boolean { + return this.userService.logged_user_id === this.pageUserId; + } +} diff --git a/src/pages/user/profile/profile.html b/src/pages/user/profile/profile.html new file mode 100644 index 0000000..da8e164 --- /dev/null +++ b/src/pages/user/profile/profile.html @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/src/pages/user/profile/profile.module.ts b/src/pages/user/profile/profile.module.ts new file mode 100644 index 0000000..93dd58c --- /dev/null +++ b/src/pages/user/profile/profile.module.ts @@ -0,0 +1,34 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; + +import { ComponentsModule } from '@components/components.module'; + +import { UserProfileDesktopComponent } from './desktop/profile-desktop.component'; +import { UserProfileMobileComponent } from './mobile/profile-mobile.component'; +import { UserProfileBannerEditModalComponent } from './modals/banner-modal/banner-edit-modal.component'; +import { UserProfileInfosEditModalComponent } from './modals/infos-modal/infos-edit-modal.component'; +import { UserProfilePictureEditModalComponent } from './modals/picture-modal/picture-edit-modal.component'; +import { UserProfileComponent } from './profile.component'; + +@NgModule({ + declarations: [ + UserProfileComponent, + UserProfilePictureEditModalComponent, + UserProfileBannerEditModalComponent, + UserProfileInfosEditModalComponent, + UserProfileDesktopComponent, + UserProfileMobileComponent, + ], + exports: [ + UserProfileComponent, + UserProfilePictureEditModalComponent, + UserProfileBannerEditModalComponent, + UserProfileInfosEditModalComponent, + UserProfileDesktopComponent, + UserProfileMobileComponent, + ], + imports: [FormsModule, CommonModule, ComponentsModule, ReactiveFormsModule, TranslateModule], +}) +export class UserPageModule {} diff --git a/src/pages/user/profile/profile.scss b/src/pages/user/profile/profile.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/verify/verify.component.ts b/src/pages/verify/verify.component.ts new file mode 100644 index 0000000..2dbec8e --- /dev/null +++ b/src/pages/verify/verify.component.ts @@ -0,0 +1,12 @@ +import { Component, Inject } from '@angular/core'; + +import { PageService } from '@services/page.service'; + +@Component({ + selector: 'sith-verify', + templateUrl: './verify.html', + styleUrls: ['./verify.scss'], +}) +export class VerifyComponent { + public constructor(@Inject(PageService) public readonly page: PageService) {} +} diff --git a/src/pages/verify/verify.html b/src/pages/verify/verify.html new file mode 100644 index 0000000..acb3772 --- /dev/null +++ b/src/pages/verify/verify.html @@ -0,0 +1,7 @@ +
+ + + + +

{{ 'verify.description' | translate }}

+
diff --git a/src/pages/verify/verify.scss b/src/pages/verify/verify.scss new file mode 100644 index 0000000..890c241 --- /dev/null +++ b/src/pages/verify/verify.scss @@ -0,0 +1,26 @@ +.content { + min-height: 100vh; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + font-family: Inter, sans-serif; + + >.description { + color: var(--text-color-dynamic); + text-align: center; + margin: 20px; + } + + >.logo { + width: 200px; + height: 200px; + margin-bottom: 20px; + } + + >.button { + margin-top: 20px; + } +} diff --git a/src/services/api.service.ts b/src/services/api.service.ts new file mode 100644 index 0000000..b04d5ee --- /dev/null +++ b/src/services/api.service.ts @@ -0,0 +1,245 @@ +import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http'; +import { Inject, Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +import { environment } from '@environments/environment'; + +export type ApiError = Omit & { error: T }; +export type Endpoint = `/${string}`; + +interface ResponseTypeMap { + arraybuffer: ArrayBuffer; + blob: Blob; + text: string; +} + +export type ResponseType = { + [K in keyof ResponseTypeMap]: ResponseTypeMap[K] extends T ? K : never; +}[keyof ResponseTypeMap]; + +type ResponseTypeKeys = keyof ResponseTypeMap | 'json'; +type ResponseTypes = ResponseTypeMap[keyof ResponseTypeMap]; + +type Headers = + | HttpHeaders + | { + [header: string]: string | string[]; + }; + +@Injectable({ + providedIn: 'root', +}) +export class APIService { + public constructor(@Inject(HttpClient) private readonly http: HttpClient) {} + + private readonly DEFAULT_HEADERS = { + Authorization: `Bearer ${sessionStorage.getItem('user_token') ?? 'invalid'}`, + 'Accept-Language': localStorage.getItem('lang') ?? 'en-US', + }; + + /** + * Send a GET request to the API + * @param url API endpoint, starting with a slash + * @param responseType Response type, default to 'json' + * @returns An observable of the response + */ + public get( + url: Endpoint, + responseType?: 'json', + headers?: Headers, + ): Res extends ResponseTypes ? never : Observable; + + /** + * Send a GET request to the API, with a specific response type + * @param url API endpoint, starting with a slash + * @param responseType Response type + * @returns An observable of the response + * + * @remark generic type 'Res' should be one of the following: ArrayBuffer, Blob, string + */ + public get : never>( + url: Endpoint, + responseType: ResType, + headers?: Headers, + ): Observable; + + public get(url: Endpoint, responseType: ResponseTypeKeys = 'json', headers: Headers = {}): Observable { + return this.http.get(`${environment.API_URL}${url}`, { + headers: { ...this.DEFAULT_HEADERS, ...headers }, + responseType: responseType as 'json', + }); + } + + /** + * Send a POST request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type, default to 'json' + */ + public post( + url: Endpoint, + body: Body, + responseType?: 'json', + headers?: Headers, + ): Res extends ResponseTypes ? never : Observable; + + /** + * Send a POST request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type + * @returns An observable of the response + * + * @remark generic type 'Res' should be one of the following: ArrayBuffer, Blob, string + */ + public post : never>( + url: Endpoint, + body: Body, + responseType: ResType, + headers?: Headers, + ): Observable; + + public post( + url: Endpoint, + body: B, + responseType: ResponseTypeKeys = 'json', + headers: Headers = {}, + ): Observable { + return this.http.post(`${environment.API_URL}${url}`, body, { + headers: { ...this.DEFAULT_HEADERS, ...headers }, + responseType: responseType as 'json', + }); + } + + /** + * Send a PUT request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type, default to 'json' + */ + public put( + url: Endpoint, + body: Body, + responseType?: 'json', + headers?: Headers, + ): Res extends ResponseTypes ? never : Observable; + + /** + * Send a PUT request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type + * @returns An observable of the response + * + * @remark generic type 'Res' should be one of the following: ArrayBuffer, Blob, string + */ + public put : never>( + url: Endpoint, + body: Body, + responseType: ResType, + headers?: Headers, + ): Observable; + + public put( + url: Endpoint, + body: B, + responseType: ResponseTypeKeys = 'json', + headers: Headers = {}, + ): Observable { + return this.http.put(`${environment.API_URL}${url}`, body, { + headers: { ...this.DEFAULT_HEADERS, ...headers }, + responseType: responseType as 'json', + }); + } + + /** + * Send a PATCH request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type, default to 'json' + */ + public patch( + url: Endpoint, + body: Body, + responseType?: 'json', + headers?: Headers, + ): Res extends ResponseTypes ? never : Observable; + + /** + * Send a PATCH request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type + * @returns An observable of the response + * + * @remark generic type 'Res' should be one of the following: ArrayBuffer, Blob, string + */ + public patch : never>( + url: Endpoint, + body: Body, + responseType: ResType, + headers?: Headers, + ): Observable; + + public patch( + url: Endpoint, + body: B, + responseType: ResponseTypeKeys = 'json', + headers: Headers = {}, + ): Observable { + return this.http.patch(`${environment.API_URL}${url}`, body, { + headers: { ...this.DEFAULT_HEADERS, ...headers }, + responseType: responseType as 'json', + }); + } + + /** + * Send a DELETE request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type, default to 'json' + */ + public delete( + url: Endpoint, + responseType?: 'json', + body?: Body, + headers?: Headers, + ): Res extends ResponseTypes ? never : Observable; + + /** + * Send a DELETE request to the API + * @param url API endpoint, starting with a slash + * @param body Request body + * @param responseType Response type + * @returns An observable of the response + * + * @remark generic type 'Res' should be one of the following: ArrayBuffer, Blob, string + */ + public delete : never>( + url: Endpoint, + responseType: ResType, + body?: Body, + headers?: Headers, + ): Observable; + + public delete( + url: Endpoint, + responseType: ResponseTypeKeys = 'json', + body?: B, + headers: Headers = {}, + ): Observable { + return this.http.delete(`${environment.API_URL}${url}`, { + headers: { ...this.DEFAULT_HEADERS, ...headers }, + responseType: responseType as 'json', + body, + }); + } + + public head(url: Endpoint): Observable { + return this.http.head(`${environment.API_URL}${url}`, { headers: this.DEFAULT_HEADERS }); + } + + public options(url: Endpoint): Observable { + return this.http.options(`${environment.API_URL}${url}`, { headers: this.DEFAULT_HEADERS }); + } +} diff --git a/src/services/page.service.ts b/src/services/page.service.ts new file mode 100644 index 0000000..e3208a7 --- /dev/null +++ b/src/services/page.service.ts @@ -0,0 +1,280 @@ +import type { FontSize, Theme, ThemeEvent } from 'types'; + +import { Inject, Injectable } from '@angular/core'; +import { ActivationStart, NavigationExtras, Router } from '@angular/router'; +import { TranslateService } from '@ngx-translate/core'; +import { fromEvent, Observable, Subscription } from 'rxjs'; + +import { RouteData } from '@app-routing.module'; +import { getLanguage, getLanguageDirection } from '@utils/i18n'; + +@Injectable({ + providedIn: 'root', +}) +export class PageService { + public constructor(@Inject(TranslateService) public readonly t: TranslateService, private router: Router) { + // if language not set + if (localStorage.getItem('lang') === null) this.lang = this.DEFAULT_LANG; + + // if font size not set + if (localStorage.getItem('font_size') === null) this.font_size = '1'; + + // if theme not set + if (localStorage.getItem('theme') === null) this.theme = 'auto'; + if (localStorage.getItem('theme_event') === null) this.theme_event = this.DEFAULT_THEME_EVENT; + // or last update was yesterday and not disabled + else if (new Date().getDate() !== new Date(this.theme_event.last_update).getDate() && !this.theme_event.disabled) + this.theme_event = this.DEFAULT_THEME_EVENT; + + this.updateHTML(); + + this.resizeObservable$ = fromEvent(window, 'resize'); + this.resizeSubscription$ = this.resizeObservable$.subscribe((evt) => { + this.width = (evt.target as Window).innerWidth; + this.height = (evt.target as Window).innerHeight; + }); + + this.router.events.subscribe((event) => { + if (event instanceof ActivationStart) { + const data = event.snapshot.data as RouteData; + + if (data.title) t.get(data.title).subscribe((title: string) => (this.title = title)); + this.headless = data.headless ?? false; + this.full_width = data.full_width ?? false; + } + }); + } + + resizeObservable$: Observable; + resizeSubscription$: Subscription; + + public to(path: string | string[], extras?: NavigationExtras) { + this.router.navigate(typeof path === 'string' ? [path] : path, extras).catch((err) => { + console.error(err); + }); + } + + private updateHTML() { + document.documentElement.setAttribute('lang', this.lang); + document.documentElement.setAttribute('dir', this.isRTL() ? 'rtl' : 'ltr'); + document.documentElement.style.setProperty('--font-size', this.font_size); + + if (!this.theme_event.disabled) document.documentElement.setAttribute('data-event-theme', this.theme_event.theme); + else document.documentElement.removeAttribute('data-event-theme'); + + if (this.theme !== 'auto') document.documentElement.setAttribute('data-theme', this.theme); + else { + const prefersDark: boolean = window.matchMedia('(prefers-color-scheme: dark)').matches; + + if (prefersDark) document.documentElement.setAttribute('data-theme', 'dark'); + else document.documentElement.setAttribute('data-theme', 'light'); + } + } + + public get theme(): Theme { + return localStorage.getItem('theme') || 'auto'; + } + + public set theme(value: Theme) { + localStorage.setItem('theme', value); + this.updateHTML(); + } + + public get theme_is_dark(): boolean { + switch (this.theme) { + case 'auto': + return window.matchMedia('(prefers-color-scheme: dark)').matches; + + case 'dark': + case 'high_contrast': + return true; + + case 'light': + default: + return false; + } + } + + public get theme_event(): ThemeEvent { + const local = localStorage.getItem('theme_event'); + if (local === null) { + this.theme_event = this.DEFAULT_THEME_EVENT; + return this.DEFAULT_THEME_EVENT; + } + + return JSON.parse(local); + } + + public set theme_event(value: ThemeEvent) { + localStorage.setItem('theme_event', JSON.stringify(value)); + if (!value.disabled) document.documentElement.setAttribute('data-event-theme', value.theme); + else document.documentElement.removeAttribute('data-event-theme'); + } + + private get DEFAULT_THEME_EVENT() { + return { + theme: this.getCurrentThemeEvent(), + last_update: new Date(), + disabled: false, + }; + } + + public toggleThemeEvent(theme: ThemeEvent['theme']) { + this.theme_event = { + ...this.theme_event, + theme, + disabled: this.theme_event.theme === theme ? !this.theme_event.disabled : this.theme_event.disabled, + }; + } + + public getCurrentThemeEvent(): ThemeEvent['theme'] { + switch (new Date().getMonth()) { + case 11: + return 'christmas'; + case 9: + return 'pinktober'; + default: + return 'none'; + } + } + + public get logo() { + this.updateFavicon(); + + switch (this.theme_event.theme) { + case 'christmas': + return 'assets/logo/ae_christmas.webp'; + case 'pinktober': + return 'assets/logo/ae_pinktober.webp'; + default: + return 'assets/logo/ae.webp'; + } + } + + private updateFavicon() { + const type = this.theme_event.theme === 'none' ? 'base' : this.theme_event.theme ?? 'base'; + + const appleTouchIcon = document.querySelector('link[rel="apple-touch-icon"]'); + const icons = document.querySelectorAll('link[rel="icon"]'); + const manifest = document.querySelector('link[rel="manifest"]'); + const maskIcon = document.querySelector('link[rel="mask-icon"]'); + const shortcutIcon = document.querySelector('link[rel="shortcut icon"]'); + + const metaMSAppTileColor = document.querySelector('meta[name="msapplication-TileColor"]'); + const metaMSAppConfig = document.querySelector('meta[name="msapplication-config"]'); + const metaThemeColor = document.querySelector('meta[name="theme-color"]'); + + const colors = { + christmas: '#095228', + pinktober: '#e891dc', + base: '#ffffff', + }; + + if (appleTouchIcon) appleTouchIcon.href = `assets/favicon/${type}/apple-touch-icon.png`; + if (icons) icons.forEach((icon) => (icon.href = `assets/favicon/${type}/favicon-${icon.sizes.value}.png`)); + if (manifest) manifest.href = `assets/favicon/${type}/site.webmanifest`; + if (maskIcon) { + maskIcon.href = `assets/favicon/${type}/safari-pinned-tab.svg`; + (maskIcon as HTMLLinkElement & { color: string }).color = colors[type]; + } + if (shortcutIcon) shortcutIcon.href = `assets/favicon/${type}/favicon.ico`; + if (metaMSAppTileColor) metaMSAppTileColor.content = colors[type]; + if (metaMSAppConfig) metaMSAppConfig.content = `assets/favicon/${type}/browserconfig.xml`; + if (metaThemeColor) metaThemeColor.content = colors[type]; + } + + public get font_size(): FontSize { + return localStorage.getItem('font_size') || '1'; + } + + public set font_size(value: FontSize) { + localStorage.setItem('font_size', value); + document.documentElement.style.setProperty('--font-size', value); + } + + public get lang(): string { + return localStorage.getItem('lang') || this.DEFAULT_LANG; + } + + public set lang(value: string) { + this.setLang(value, true); + } + + private setLang(value: string, store = false) { + const parsed = getLanguage(value); + + document.documentElement.lang = parsed; + document.documentElement.dir = getLanguageDirection(parsed); + + this.t.use(parsed); + this.t.currentLang = parsed; // because ngx-translate doesn't set it automatically + + if (store) localStorage.setItem('lang', parsed); + return parsed; + } + + private get DEFAULT_LANG() { + this.t.setDefaultLang('en-US'); + return this.setLang(window.navigator.language); + } + + /** + * Set the browser title of the page + * @param {string} title The title to set + * @example p.title = 'Home'; // will set the title to 'Home - AE UTBM' + */ + public set title(title: string) { + document.title = `${title.trim()} - AE UTBM`; + } + + /** + * Get the browser title of the page + * @returns {string} The title of the page + */ + public get title(): `${string} - AE UTBM` { + return document.title.trim() as `${string} - AE UTBM`; + } + + public isRTL(): boolean { + return document.documentElement.dir === 'rtl'; + } + + /** + * Control if the page is in headless mode or not + * - If the page is in headless mode, the header, navbar will be hidden + */ + public headless = false; + + /** + * Control if the page is in full width mode or not + * - Will make the navbar centered if false + */ + public full_width = false; + + /** + * Check if the device used by the user is a mobile device + * @return {boolean} True if the device is a mobile device, false otherwise + */ + public isMobile(): boolean { + return this.width <= 768 || this.height <= 768; + } + + private __width: number = window.innerWidth; + private __height: number = window.innerHeight; + + public get width(): number { + return this.__width; + } + + private set width(value: number) { + this.__width = value; + } + + public get height(): number { + return this.__height; + } + + private set height(value: number) { + this.__height = value; + } +} diff --git a/src/services/permissions.service.ts b/src/services/permissions.service.ts new file mode 100644 index 0000000..2b1f802 --- /dev/null +++ b/src/services/permissions.service.ts @@ -0,0 +1,45 @@ +import type { PERMISSION_NAMES, OutputPermissionDto, OutputRoleDto } from '#types/api'; + +import { Inject, Injectable } from '@angular/core'; +import { Observable, map, switchMap } from 'rxjs'; + +import { APIService } from './api.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PermissionService { + public constructor(@Inject(APIService) private readonly api: APIService) {} + + public userPermissions(id: number): Observable { + return this.api.get(`/permissions/${id}`); + } + + // FIXME Move that to the API !! + // it might be better to check if the user has the permission on the server side (instead of piping) + // -> this avoid useless requests as the result of this method might decided if another request (with required perms) + // is made or not + public hasPermissions(id: number, permissions: PERMISSION_NAMES[]): Observable> { + return this.api.get(`/users/${id}/permissions`).pipe( + switchMap((perms) => { + return this.api.get(`/users/${id}/roles`).pipe(map((roles) => ({ perms, roles }))); + }), + map((res) => { + const out: Record = {}; + + const userPerms = [ + ...res.perms.filter((p) => p.revoked !== true).map((p) => p.name), + ...res.roles + .filter((p) => p.revoked !== true) + .map((p) => p.permissions) + .flat(), + ].unique(); + + if (userPerms.includes('ROOT')) permissions.forEach((p) => (out[p] = true)); + else permissions.forEach((p) => (out[p] = userPerms.includes(p))); + + return out as Record; + }), + ); + } +} diff --git a/src/services/promotion.service.ts b/src/services/promotion.service.ts new file mode 100644 index 0000000..c3fdcc1 --- /dev/null +++ b/src/services/promotion.service.ts @@ -0,0 +1,36 @@ +import type { imageURL } from '#types'; +import type { OutputErrorResponseDto } from '#types/api'; + +import { Inject, Injectable } from '@angular/core'; +import { Observable, catchError, map, of, throwError } from 'rxjs'; + +import { APIService, ApiError } from './api.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PromotionService { + public constructor(@Inject(APIService) private readonly api: APIService) {} + + public promotionPicture(id: number): Observable { + return this.api.get(`/promotions/${id}/logo`, 'arraybuffer').pipe( + catchError((err: ApiError) => { + const error: OutputErrorResponseDto = err.error.toJSON(); + + // If the user has no picture, return undefined + if (error.statusCode === 404) return of(undefined); + + // If any other error, throw it for later handling + return throwError(() => ({ error: error })); + }), + map((data) => { + // convert the arraybuffer to blob url + if (data) return data.toImageURL(); + + // If the user has no picture, return undefined + // (should not happen as we catch the 404 error) + return undefined; + }), + ); + } +} diff --git a/src/services/snackbar.service.ts b/src/services/snackbar.service.ts new file mode 100644 index 0000000..a24c803 --- /dev/null +++ b/src/services/snackbar.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; + +import { SnackbarComponent } from '@components/common/snackbar/snackbar.component'; + +@Injectable({ + providedIn: 'root', +}) +export class SnackbarService { + private snackbarComponent: SnackbarComponent | undefined; + + registerSnackbarComponent(snackbarComponent: SnackbarComponent) { + this.snackbarComponent = snackbarComponent; + } + + private show(message: string, title: string, type?: 'error' | 'success') { + if (this.snackbarComponent) this.snackbarComponent.show(message, title, type); + } + + success(message: string, title: string) { + this.show(message, title, 'success'); + } + + error(message = 'Error', errors: string[], status_code: number) { + this.show(errors?.join('\n'), `${status_code}: ${message}`, 'error'); + } +} diff --git a/src/services/user.service.ts b/src/services/user.service.ts new file mode 100644 index 0000000..a21c470 --- /dev/null +++ b/src/services/user.service.ts @@ -0,0 +1,149 @@ +import type { email, imageURL } from '#types'; +import type { + OutputErrorResponseDto, + OutputFileDto, + OutputUserDto, + OutputResponseDto, + OutputTokenDto, + InputSignInDto, +} from '#types/api'; + +import { Inject, Injectable } from '@angular/core'; +import { Observable, catchError, map, of, tap, throwError } from 'rxjs'; + +import { APIService, ApiError } from './api.service'; + +@Injectable({ + providedIn: 'root', +}) +export class UserService { + public constructor(@Inject(APIService) private readonly api: APIService) {} + + public login(email: email, password: string): Observable { + return this.api + .post(`/auth/login`, { + email, + password, + }) + .pipe( + tap((data) => { + sessionStorage.setItem('user_token', data.token); + sessionStorage.setItem('user_id', data.user_id.toString()); + }), + map(() => void 0), + ); + } + + public isLoggedIn(): boolean { + return sessionStorage.getItem('user_token') !== null && sessionStorage.getItem('user_id') !== null; + } + + public get logged_user_id(): number { + const id = sessionStorage.getItem('user_id'); + if (id === null) { + this.logout(); + return -1; // TODO throw ? + } + + return parseInt(id, 10); + } + + public logout(): Observable { + return new Observable((subscriber) => { + sessionStorage.clear(); + + subscriber.next(); + subscriber.complete(); + }); + } + + public user(id: number, private_data = false): Observable { + if (private_data) return this.api.get(`/users/${id}/data`); + return this.api.get(`/users/${id}/data/public`); + } + + public userPicture(id: number): Observable { + return this.api.get(`/users/${id}/picture`, 'arraybuffer').pipe( + catchError((err: ApiError) => { + const error: OutputResponseDto = err.error.toJSON(); + + // If the user has no picture, return undefined + if (error.statusCode === 404) return of(undefined); + + // If any other error, throw it for later handling + return throwError(() => ({ error: error })); + }), + map((data) => { + // convert the arraybuffer to base64 + if (data) return data.toImageURL(); + + // If the user has no picture, return undefined + // (should not happen as we catch the 404 error) + return undefined; + }), + ); + } + + public updateUserPicture(user_id: number, form: FormData): Observable { + return this.api.post(`/users/${user_id}/picture`, form); + } + + public deleteUserPicture(user_id: number): Observable { + return this.api.delete(`/users/${user_id}/picture`); + } + + public userBanner(id: number): Observable { + return this.api.get(`/users/${id}/banner`, 'arraybuffer').pipe( + catchError((err: ApiError) => { + const error: OutputErrorResponseDto = err.error.toJSON(); + + // If the user has no picture, return undefined + if (error.statusCode === 404) return of(undefined); + + // If any other error, throw it for later handling + return throwError(() => ({ error: error })); + }), + map((data) => { + // convert the arraybuffer to base64 + if (data) return data.toImageURL(); + + // If the user has no picture, return undefined + // (should not happen as we catch the 404 error) + return undefined; + }), + ); + } + + public updateUserBanner(user_id: number, form: FormData): Observable { + return this.api.post(`/users/${user_id}/banner`, form); + } + + public deleteUserBanner(user_id: number): Observable { + return this.api.delete(`/users/${user_id}/banner`); + } + + public userFileData(file_id: number): Observable { + return this.api.get(`/files/${file_id}/data`); + } + + // TODO: to be implemented (waiting for API) + // maybe in its own service ? + public userNotifications(id: number): Observable<[]> { + console.warn('NYI: userNotifications', id); + + return new Observable((subscriber) => { + subscriber.next([]); + subscriber.complete(); + }); + } + + // TODO: to be implemented (waiting for API) + public userNotificationsCount(id: number): Observable { + console.warn('NYI: userNotificationsCount'); + + return new Observable((subscriber) => { + subscriber.next(id); + subscriber.complete(); + }); + } +} diff --git a/src/styles/animations.scss b/src/styles/animations.scss new file mode 100644 index 0000000..f98afae --- /dev/null +++ b/src/styles/animations.scss @@ -0,0 +1,49 @@ +@keyframes slide { + 0% { + transform: translateX(100%); + } + + 100% { + transform: translateX(0); + } +} + +@keyframes slide-rtl { + 0% { + transform: translateX(-100%); + } + + 100% { + transform: translateX(0); + } +} + +@keyframes fade { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fade-out { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes move-up { + 0% { + transform: translateY(0); + } + + 100% { + transform: translateY(-100%); + } +} diff --git a/src/styles/inter.scss b/src/styles/inter.scss new file mode 100644 index 0000000..c15698c --- /dev/null +++ b/src/styles/inter.scss @@ -0,0 +1,62 @@ +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-Thin.ttf' format('truetype'); + font-weight: 100; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-ExtraLight.ttf' format('truetype'); + font-weight: 200; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-Light.ttf' format('truetype'); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-Regular.ttf' format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-Medium.ttf' format('truetype'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-SemiBold.ttf' format('truetype'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-Bold.ttf' format('truetype'); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-ExtraBold.ttf' format('truetype'); + font-weight: 800; + font-style: normal; +} + +@font-face { + font-family: Inter; + src: '../assets/fonts/Inter/Inter-Black.ttf' format('truetype'); + font-weight: 900; + font-style: normal; +} diff --git a/src/styles/roboto.scss b/src/styles/roboto.scss new file mode 100644 index 0000000..d686b43 --- /dev/null +++ b/src/styles/roboto.scss @@ -0,0 +1,83 @@ +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Thin.ttf' format('truetype'); + font-weight: 100; + font-style: normal; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-ThinItalic.ttf' format('truetype'); + font-weight: 100; + font-style: italic; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Light.ttf' format('truetype'); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-LightItalic.ttf' format('truetype'); + font-weight: 300; + font-style: italic; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Regular.ttf' format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Italic.ttf' format('truetype'); + font-weight: 400; + font-style: italic; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Medium.ttf' format('truetype'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-MediumItalic.ttf' format('truetype'); + font-weight: 500; + font-style: italic; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Bold.ttf' format('truetype'); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-BoldItalic.ttf' format('truetype'); + font-weight: 700; + font-style: italic; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-Black.ttf' format('truetype'); + font-weight: 900; + font-style: normal; +} + +@font-face { + font-family: Roboto; + src: '../assets/fonts/Roboto/Roboto-BlackItalic.ttf' format('truetype'); + font-weight: 900; + font-style: italic; +} diff --git a/src/styles/styles.scss b/src/styles/styles.scss new file mode 100644 index 0000000..f0f0ccf --- /dev/null +++ b/src/styles/styles.scss @@ -0,0 +1,86 @@ +@import './roboto'; +@import './inter'; +@import './themes'; +@import './animations'; + +:root { + --max-page-width: 1080px; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +body, +html { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + background-color: var(--background-color); +} + +/* Firefox */ +* { + scrollbar-width: thin; + scrollbar-color: rgb(0 0 0 / 25%) transparent; +} + +/* Chrome, Edge, and Safari */ +*::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +*::-webkit-scrollbar-track { + background: transparent; +} + +*::-webkit-scrollbar-thumb { + background-color: rgb(0 0 0 / 25%); + border-radius: 10px; + border: none; +} + +input[type="date"] { + + &::-webkit-inner-spin-button, + &::-webkit-calendar-picker-indicator { + display: none; + appearance: none; + } +} + +// "deactivate" autofill white background +// you can't directly change the background color of the autofill +// so we have to change the transition time to a very long time (1 week here) +input { + + &:-webkit-autofill, + &:-webkit-autofill:focus { + transition: background-color 604800s 0s, color 604800s 0s; + } + + &[data-autocompleted] { + background-color: transparent !important; + } +} + +.global-link { + font-family: Inter, sans-serif; + font-size: calc(14px * var(--font-size)); + font-style: italic; + line-height: 17px; + text-decoration: none; + color: var(--dark-blue); + + &:hover { + color: var(--blue); + } + + &:visited { + color: var(--purple); + } +} diff --git a/src/styles/themes.scss b/src/styles/themes.scss new file mode 100644 index 0000000..00b5f49 --- /dev/null +++ b/src/styles/themes.scss @@ -0,0 +1,97 @@ +:root { + --text-color: #000; + --text-color-dark-bg: #ddd; + --text-color-dark-bg-placeholder: #888; + --darkened: rgb(0 0 0 / 50%); + --navbar-background-color: var(--gray4); + --navbar-text-color: var(--text-color-dark-bg); + --navbar-user-icon-light-color: #c6cdd5; + --navbar-user-icon-dark-color: var(--gray3-hover); +} + +:root[data-theme="light"] { + --background-color: #ecf2f8; + --background-color-lighter: #fafafa; + --red: #ff1a0a; + --red-hover: #ff1a0a80; + --orange: #faa356; + --orange-hover: #faa35680; + --green: #7ce38b; + --blue: #78c1ff; + --blue-hover: #78c1ff80; + --dark-blue: #7597d1; + --purple: #cea5fb; + --purple-hover: #cea5fb80; + --gray4: #161b22; + --gray3: #21262d; + --gray2: #a5afb9; + --gray1: #c6cdd5; + --gray4-hover: #161b2280; + --gray3-hover: #21262d80; + --gray2-hover: #a5afb980; + --gray1-hover: #c6cdd580; + --text-color-dynamic: #000; + --text-disabled-color-dynamic: #888; +} + +:root[data-theme="dark"] { + --background-color: #0d1117; + --background-color-lighter: #131922; + --red: #aa3028; + --red-hover: #aa302880; + --orange: #e27c22; + --orange-hover: #e27c2280; + --green: #2d8655; + --blue: #107b82; + --blue-hover: #107b8280; + --dark-blue: #3592e4; + --purple: #cea5fb; + --purple-hover: #cea5fb80; + --gray4: #12161d; + --gray3: #161b22; + --gray2: #1c2128; + --gray1: #21262d; + --gray4-hover: #12161d80; + --gray3-hover: #161b2280; + --gray2-hover: #1c212880; + --gray1-hover: #21262d80; + --text-color-dynamic: #ddd; + --text-disabled-color-dynamic: #888; +} + +:root[data-event-theme="pinktober"] { + --navbar-background-color: #e891dc; + --navbar-text-color: #400547; + --navbar-user-icon-light-color: #400547; + --navbar-user-icon-dark-color: var(--purple-hover); +} + +:root[data-event-theme="christmas"] { + --navbar-background-color: #095228; + --navbar-text-color: #002111; + --navbar-user-icon-light-color: #002111; + --navbar-user-icon-dark-color: #095228; +} + +:root[data-theme="high_contrast"] { + --background-color: #000; + --red: #f00; + --orange: #ffa500; + --green: #0f0; + --blue: #00fff2; + --dark-blue: #00fff2; + --purple: #f33bee; + --gray4: #111; + --gray3: #222; + --gray2: #333; + --gray1: #444; + --gray4-hover: #00000080; + --gray3-hover: #11111180; + --gray2-hover: #22222280; + --gray1-hover: #33333380; + --text-color-dynamic: #fff; + --navbar-background-color: var(--gray4); + --navbar-text-color: var(--text-color-dark-bg); + --navbar-user-icon-light-color: var(--text-color-dark-bg); + --navbar-user-icon-dark-color: var(--gray1); +} diff --git a/src/utils/i18n.spec.ts b/src/utils/i18n.spec.ts new file mode 100644 index 0000000..1f864a8 --- /dev/null +++ b/src/utils/i18n.spec.ts @@ -0,0 +1,94 @@ +import { HttpClient } from '@angular/common/http'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; + +import { HttpLoaderFactory, TranslateHttpLoader, getLanguage, getLanguageDirection } from './i18n'; + +import '@exported/global/@types'; + +describe('i18n', () => { + let httpTestingController: HttpTestingController; + let translateHttpLoader: TranslateHttpLoader; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [{ provide: TranslateHttpLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] }], + }); + + httpTestingController = TestBed.inject(HttpTestingController); + translateHttpLoader = TestBed.inject(TranslateHttpLoader); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + describe('getLanguage', () => { + it('should return the language filename for the given language code', () => { + expect(getLanguage('en')).toBe('en-US'); + }); + + it('should return the default language filename if no matching language is found', () => { + expect(getLanguage('does-not-exist')).toBe('en-US'); + }); + }); + + describe('getLanguageDirection', () => { + it('should return the direction of the given language', () => { + expect(getLanguageDirection('ar-SA')).toBe('rtl'); + }); + + it('should return the default language direction if no matching language is found', () => { + expect(getLanguageDirection('does-not-exist')).toBe('ltr'); + }); + }); + + describe('getAllKeysOfObject', () => { + it('should return all keys of the object and its nested objects', () => { + const obj = { a: 1, b: { c: 2, d: 3 } }; + expect(Object.keysRecursive(obj)).toEqual(['a', 'b.c', 'b.d']); + }); + }); + + describe('TranslateHttpLoader', () => { + it('should load the base language file and merge it with the given language file', () => { + const langData = { + greeting: 'Hello', + farewell: 'Goodbye', + }; + + const baseLangData = { + greeting: 'Hello', + question: 'How are you?', + }; + + translateHttpLoader.getTranslation('fr-FR').subscribe((mergedData) => { + expect(mergedData).toEqual(Object.merge(baseLangData, langData)); + }); + + const langRequest = httpTestingController.expectOne('./assets/i18n/fr-FR.json'); + langRequest.flush(langData); + + const baseLangRequest = httpTestingController.expectOne('./assets/i18n/en-US.json'); + baseLangRequest.flush(baseLangData); + }); + + it('should gracefully handle errors when loading the language file', () => { + const baseLangData = { + greeting: 'Hello', + question: 'How are you?', + }; + + translateHttpLoader.getTranslation('invalid').subscribe((mergedData) => { + expect(mergedData).toEqual(Object.merge(baseLangData)); + }); + + const langRequest = httpTestingController.expectOne('./assets/i18n/invalid.json'); + langRequest.error(new ProgressEvent('error'), { status: 404 }); + + const baseLangRequest = httpTestingController.expectOne('./assets/i18n/en-US.json'); + baseLangRequest.flush(baseLangData); + }); + }); +}); diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 0000000..bc683bb --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,93 @@ +import type { Path } from '#types'; +import type { LangFile, Language } from 'types'; + +import { HttpClient } from '@angular/common/http'; +import { Inject, Injectable } from '@angular/core'; +import { TranslateLoader } from '@ngx-translate/core'; +import { Observable, catchError, forkJoin, from, map, of, switchMap } from 'rxjs'; + +import DEfAULT_LANG from '@assets/i18n/en-US.json'; +import LANGS from '@assets/i18n/languages.json'; + +export const LANGUAGES: Language[] = LANGS as unknown as Language[]; +export const DEFAULT_LANGUAGE = 'en-US'; +export type LangKeys = Path; + +/** + * Get the language filename from the given language code + * @param {string} lang language code to be analyzed + * @returns {string} The filename of the language within the i18n asset folder + * + * @example getLanguage('en-US') // en-US.json + * @example getLanguage('en') // en-US.json + * @example getLanguage('does-not-exist') // en-US.json + */ +export function getLanguage(lang: string): string { + const language = LANGUAGES.filter((l) => l.codes.includes(lang))[0]; + return language?.filename ?? DEFAULT_LANGUAGE; +} + +/** + * Get the read direction of the given language + * @param {string} lang language code to be analyzed + * @returns {Language['direction']} The read direction of the language + */ +export function getLanguageDirection(lang: string): Language['direction'] { + const language: Language | undefined = LANGUAGES.filter((l) => l.codes.includes(lang))[0]; + return language?.direction ?? getLanguageDirection(DEFAULT_LANGUAGE); +} + +/** + * Get the completion of a language based on the default language (English) + * @param {string} lang the language to get the completion of + * @returns {Observable} The completion of the language in percentage + */ +export function getLanguageCompletion(lang: string): Observable { + return from(import(`../assets/i18n/${DEFAULT_LANGUAGE}.json`)).pipe( + switchMap((base: typeof DEfAULT_LANG) => + from(import(`../assets/i18n/${getLanguage(lang)}.json`)).pipe( + map((language: typeof DEfAULT_LANG) => { + const baseKeys = Object.keysRecursive(base); + const languageKeys = Object.keysRecursive(language); + const missingKeys = baseKeys.filter((key) => !languageKeys.includes(key)); + return Math.floor((1 - missingKeys.length / baseKeys.length) * 100); + }), + catchError(() => of(0)), + ), + ), + ); +} + +/** + * Reimplement the TranslateHttpLoader to load the base language (English) + * and merge it with the given language + */ +@Injectable() +export class TranslateHttpLoader implements TranslateLoader { + public constructor( + private http: HttpClient, + @Inject(String) public prefix: string, + @Inject(String) public suffix: string, + ) {} + + public getTranslation(lang: string): Observable { + const langFile = `${this.prefix}${lang}${this.suffix}`; + const baseLangFile = `${this.prefix}${DEFAULT_LANGUAGE}${this.suffix}`; + + const langFile$ = this.http.get>(langFile).pipe(catchError(() => of({}))); + const baseLangFile$ = this.http.get(baseLangFile); + + return forkJoin([langFile$, baseLangFile$]).pipe( + map(([langData, baseLangData]) => Object.merge(baseLangData, langData)), + ); + } +} + +/** + * Factory function to create the TranslateHttpLoader + * @param {HttpClient} http the HttpClient to be used by the TranslateHttpLoader + * @returns {TranslateHttpLoader} The TranslateHttpLoader + */ +export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader { + return new TranslateHttpLoader(http, './assets/i18n/', '.json'); +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..374cc9d --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4e6f80f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,56 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "resolveJsonModule": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "paths": { + "#types/api": [ + "src/exported/api/@types/index.d.ts" + ], + "#types": [ + "src/exported/global/@types/index.d.ts" + ], + "#types/sith": [ + "types/index.d.ts" + ], + "@*": [ + "src/*" + ] + }, + "lib": [ + "ES2022", + "dom", + "esnext.asynciterable" + ], + "typeRoots": [ + "src/exported/global/@types", + "src/exported/api/@types", + "types", + "node_modules/@types" + ], + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000..be7e9da --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/types/a10y.d.ts b/types/a10y.d.ts new file mode 100644 index 0000000..9224546 --- /dev/null +++ b/types/a10y.d.ts @@ -0,0 +1,17 @@ +export type Theme = 'auto' | 'light' | 'dark' | 'high_contrast'; +export type ThemeEvent = { + theme: 'none' | 'pinktober' | 'christmas'; + last_update: Date; + disabled: boolean; +}; + +export type FontSize = '0.75' | '1' | '1.25'; + +export interface SelectComponentOption { + /** Optional image to display next to the label */ + image?: string; + /** The label to display */ + label: string; + /** The value to return */ + value: string; +} diff --git a/types/i18n.d.ts b/types/i18n.d.ts new file mode 100644 index 0000000..5f2353c --- /dev/null +++ b/types/i18n.d.ts @@ -0,0 +1,19 @@ +export interface LangFile { + [key: string]: string | LangFile; +} + +/** + * A language + */ +export interface Language { + /** The language codes @example ['en', 'en-US', 'en-GB'] */ + codes: Array; + /** The language filename in the 'assets/i18n/' directory */ + filename: string; + /** The language label, translated in the language itself */ + label: string; + /** The language flag */ + image: string; + /** The language read direction */ + direction: 'ltr' | 'rtl'; +} diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..3623990 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,16 @@ +import { base64 } from '#types'; + +export * from './i18n'; +export * from './a10y'; + +export interface ImageCropperSetting { + width: number; + height: number; +} + +export interface ImageCropperResult { + imageData: Cropper.ImageData; + cropData: Cropper.CropBoxData; + blob?: Blob; + dataUrl?: base64; +}