From 871da18a800eb5847306dbb8d5c3d1bc4e80e96a Mon Sep 17 00:00:00 2001 From: Moroine Bentefrit Date: Tue, 12 Nov 2024 13:18:38 +0100 Subject: [PATCH 1/2] chore: suppression preview, mongodb, metabase, smtp & dead code --- .bin/commands.sh | 24 +- .bin/scripts/build-images.sh | 2 +- .bin/scripts/deploy-app.sh | 16 +- .bin/scripts/get-vault-password-client.sh | 2 +- .bin/scripts/run-playbook.sh | 4 +- .bin/scripts/seed-apply.sh | 41 - .bin/scripts/seed-update.sh | 44 - .bin/scripts/setup-local-env.sh | 6 - .bin/zsh-completion | 4 - .gitattributes | 1 - .github/workflows/ci.yml | 7 - .github/workflows/deploy_preview.yml | 162 -- .github/workflows/preview.yml | 22 - .github/workflows/preview_cleanup.yml | 41 - .gitignore | 2 - .infra/.env_server | 14 - .infra/.gitignore | 1 - .infra/ansible/deploy.yml | 52 - .infra/ansible/preview.yml | 26 - .infra/ansible/preview_cleanup.yml | 34 - .infra/ansible/tasks/files_copy.yml | 38 +- .infra/ansible/tasks/preview_pr.yml | 133 -- .infra/docker-compose.preview-system.yml | 148 -- .infra/docker-compose.preview.yml | 70 - .infra/docker-compose.production.yml | 60 - .infra/docker-compose.recette.yml | 38 - .infra/env.ini | 7 - .infra/files/configs/mailpit/.gitkeep | 0 .infra/files/configs/mailpit/auth | 1 - .../files/configs/metabase/setup-metabase.sh | 52 - .../files/configs/mongodb/mongo_keyfile.txt | 1 - .infra/files/configs/mongodb/mongod.conf | 8 - .infra/files/configs/mongodb/seed.gpg | 3 - .../locations/70_smtp.conf.template | 8 - .../locations/80_metabase.conf.template | 8 - .infra/files/data/smtp/.gitkeep | 0 .infra/files/scripts/migrations-status.sh | 5 - .infra/files/scripts/migrations-up.sh | 18 - .infra/files/scripts/seed.sh | 23 - .../files/scripts/trigger-indexes-creation.sh | 17 - .infra/local/mongo_keyfile | 1 - .infra/local/mongod.conf | 8 - .infra/vault/vault.yml | 409 +---- .prettierignore | 3 +- .talismanrc | 14 +- .vscode/terminals.json | 2 +- PROJECT_README.md | 15 - README.md | 267 +--- docker-bake.json | 5 +- docker-compose.yml | 39 - docs/Vault.md | 1 - docs/developpement/developpement.md | 98 +- docs/infrastructure.md | 1 - docs/infrastructure/architecture.md | 4 - docs/infrastructure/preview.md | 5 - package.json | 17 +- server/.env.test | 14 - server/package.json | 4 +- server/src/commands.ts | 94 +- server/src/common/services/mailer/mailer.ts | 134 -- server/src/common/services/sentry/sentry.ts | 41 - server/src/common/utils/asyncUtils.ts | 19 - server/src/common/utils/cryptoUtils.ts | 29 - server/src/common/utils/jwtUtils.ts | 61 - server/src/common/utils/mongodbUtils.ts | 180 --- server/src/config.ts | 40 +- .../db/migrations/20230511154647-example.ts | 7 - server/src/index.ts | 14 - server/src/modules/actions/auth.actions.ts | 47 - server/src/modules/actions/emails.actions.ts | 113 -- .../src/modules/actions/sessions.actions.ts | 60 - server/src/modules/actions/users.actions.ts | 53 - server/src/modules/jobs/db/recreateIndexes.ts | 12 - .../src/modules/jobs/db/schemaValidation.ts | 24 - server/src/modules/jobs/jobs.ts | 56 - .../src/modules/jobs/migrations/migrations.ts | 83 - .../src/modules/server/admin/user.routes.ts | 65 - server/src/modules/server/auth.routes.ts | 91 -- server/src/modules/server/core.routes.ts | 11 - server/src/modules/server/emails.routes.ts | 106 -- .../server/middlewares/authMiddleware.ts | 66 - server/src/modules/server/server.ts | 38 - server/src/modules/server/user.routes.ts | 23 - .../modules/server/utils/password.utils.ts | 39 - server/src/security/accessTokenService.ts | 165 -- server/src/security/authenticationService.ts | 152 -- server/src/security/authorisationService.ts | 153 -- server/static/emails/common/footer.ejs | 21 - server/static/emails/common/head.ejs | 34 - server/static/emails/common/header.ejs | 7 - server/static/emails/common/signature.ejs | 9 - server/static/emails/reset_password.mjml.ejs | 32 - server/tests/globalSetup.ts | 31 - server/tests/integration/server.test.ts | 36 +- .../modules/jobs/db/schemaValidation.test.ts | 156 -- server/tests/routes/auth.route.test.ts | 222 --- server/tests/routes/users.route.test.ts | 122 -- server/tests/utils/mongo.utils.ts | 37 - .../utils/security/accessTokenService.test.ts | 203 --- .../security/authorisationService.test.ts | 156 -- server/tsup.config.ts | 10 +- .../mongoSchemaBuilder.test.ts.snap | 238 --- .../mongoSchema/mongoSchemaBuilder.test.ts | 12 - .../generateOpenapi.test.ts.snap | 229 --- .../helpers/openapi/generateOpenapi.test.ts | 10 - shared/helpers/openapi/generateOpenapi.ts | 160 -- shared/helpers/zodWithOpenApi.ts | 6 - shared/models/common.ts | 12 - shared/models/email_denied.model.ts | 25 - shared/models/email_event.model.ts | 41 - shared/models/email_event/email_templates.ts | 23 - shared/models/models.ts | 19 - shared/models/session.model.ts | 27 - shared/models/user.model.ts | 89 -- shared/package.json | 7 +- shared/routes/admin/admin.routes.ts | 47 - shared/routes/auth.routes.ts | 77 - shared/routes/cerfa.routes.ts | 1 - shared/routes/common.routes.ts | 66 +- shared/routes/controls.routes.ts | 1 - shared/routes/core.routes.ts | 25 +- shared/routes/emails.routes.ts | 69 - shared/routes/geo.routes.ts | 1 - shared/routes/index.test.ts | 24 +- shared/routes/index.ts | 19 +- shared/routes/naf.routes.ts | 1 - shared/routes/siret.routes.ts | 1 - shared/routes/tco.routes.ts | 1 - shared/routes/user.routes.ts | 20 - ui/app/(application)/admin/layout.tsx | 18 - .../utilisateurs/[id]/components/UserView.tsx | 50 - .../admin/utilisateurs/[id]/page.tsx | 15 - .../utilisateurs/components/UserList.tsx | 88 -- .../(application)/admin/utilisateurs/page.tsx | 20 - .../auth/components/FormContainer.tsx | 15 - ui/app/(application)/auth/connexion/page.tsx | 106 -- .../auth/modifier-mot-de-passe/page.tsx | 134 -- .../auth/mot-de-passe-oublie/page.tsx | 87 -- ui/app/(application)/cgu/components/Cgu.tsx | 377 ----- ui/app/(application)/cgu/page.tsx | 14 - .../components/breadcrumb/Breadcrumb.tsx | 41 - .../components/header/Header.tsx | 44 +- .../components/header/header.utils.ts | 32 +- ui/app/(application)/compte/profil/page.tsx | 134 -- .../components/DonneesPersonnelles.tsx | 164 -- .../donnees-personnelles/page.tsx | 14 - ui/app/(application)/layout.tsx | 22 +- .../components/MentionLegales.tsx | 133 -- .../(application)/mentions-legales/page.tsx | 14 - .../components/PolitiqueConfidentialite.tsx | 278 ---- .../politique-confidentialite/page.tsx | 12 - ui/app/(application)/sentry/page.tsx | 86 -- ui/app/sitemap.ts | 1 - ui/config.public.ts | 28 +- ui/context/AuthContext.tsx | 25 - ui/next.config.js | 20 + vitest.workspace.ts | 1 - yarn.lock | 1338 +---------------- 158 files changed, 208 insertions(+), 9456 deletions(-) delete mode 100755 .bin/scripts/seed-apply.sh delete mode 100755 .bin/scripts/seed-update.sh delete mode 100644 .github/workflows/deploy_preview.yml delete mode 100644 .github/workflows/preview.yml delete mode 100644 .github/workflows/preview_cleanup.yml delete mode 100644 .infra/ansible/preview.yml delete mode 100644 .infra/ansible/preview_cleanup.yml delete mode 100644 .infra/ansible/tasks/preview_pr.yml delete mode 100644 .infra/docker-compose.preview-system.yml delete mode 100644 .infra/docker-compose.preview.yml delete mode 100644 .infra/docker-compose.recette.yml delete mode 100644 .infra/files/configs/mailpit/.gitkeep delete mode 100644 .infra/files/configs/mailpit/auth delete mode 100755 .infra/files/configs/metabase/setup-metabase.sh delete mode 100644 .infra/files/configs/mongodb/mongo_keyfile.txt delete mode 100644 .infra/files/configs/mongodb/mongod.conf delete mode 100644 .infra/files/configs/mongodb/seed.gpg delete mode 100644 .infra/files/configs/reverse_proxy/locations/70_smtp.conf.template delete mode 100644 .infra/files/configs/reverse_proxy/locations/80_metabase.conf.template delete mode 100644 .infra/files/data/smtp/.gitkeep delete mode 100755 .infra/files/scripts/migrations-status.sh delete mode 100755 .infra/files/scripts/migrations-up.sh delete mode 100755 .infra/files/scripts/seed.sh delete mode 100755 .infra/files/scripts/trigger-indexes-creation.sh delete mode 100644 .infra/local/mongo_keyfile delete mode 100644 .infra/local/mongod.conf delete mode 100644 PROJECT_README.md delete mode 100644 docker-compose.yml delete mode 100644 docs/infrastructure/preview.md delete mode 100644 server/src/common/services/mailer/mailer.ts delete mode 100644 server/src/common/utils/cryptoUtils.ts delete mode 100644 server/src/common/utils/jwtUtils.ts delete mode 100644 server/src/common/utils/mongodbUtils.ts delete mode 100644 server/src/db/migrations/20230511154647-example.ts delete mode 100644 server/src/modules/actions/auth.actions.ts delete mode 100644 server/src/modules/actions/emails.actions.ts delete mode 100644 server/src/modules/actions/sessions.actions.ts delete mode 100644 server/src/modules/actions/users.actions.ts delete mode 100644 server/src/modules/jobs/db/recreateIndexes.ts delete mode 100644 server/src/modules/jobs/db/schemaValidation.ts delete mode 100644 server/src/modules/jobs/jobs.ts delete mode 100644 server/src/modules/jobs/migrations/migrations.ts delete mode 100644 server/src/modules/server/admin/user.routes.ts delete mode 100644 server/src/modules/server/auth.routes.ts delete mode 100644 server/src/modules/server/emails.routes.ts delete mode 100644 server/src/modules/server/middlewares/authMiddleware.ts delete mode 100644 server/src/modules/server/user.routes.ts delete mode 100644 server/src/modules/server/utils/password.utils.ts delete mode 100644 server/src/security/accessTokenService.ts delete mode 100644 server/src/security/authenticationService.ts delete mode 100644 server/src/security/authorisationService.ts delete mode 100644 server/static/emails/common/footer.ejs delete mode 100644 server/static/emails/common/head.ejs delete mode 100644 server/static/emails/common/header.ejs delete mode 100644 server/static/emails/common/signature.ejs delete mode 100644 server/static/emails/reset_password.mjml.ejs delete mode 100644 server/tests/globalSetup.ts delete mode 100644 server/tests/modules/jobs/db/schemaValidation.test.ts delete mode 100644 server/tests/routes/auth.route.test.ts delete mode 100644 server/tests/routes/users.route.test.ts delete mode 100644 server/tests/utils/mongo.utils.ts delete mode 100644 server/tests/utils/security/accessTokenService.test.ts delete mode 100644 server/tests/utils/security/authorisationService.test.ts delete mode 100644 shared/helpers/mongoSchema/__snapshots__/mongoSchemaBuilder.test.ts.snap delete mode 100644 shared/helpers/mongoSchema/mongoSchemaBuilder.test.ts delete mode 100644 shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap delete mode 100644 shared/helpers/openapi/generateOpenapi.test.ts delete mode 100644 shared/helpers/openapi/generateOpenapi.ts delete mode 100644 shared/helpers/zodWithOpenApi.ts delete mode 100644 shared/models/common.ts delete mode 100644 shared/models/email_denied.model.ts delete mode 100644 shared/models/email_event.model.ts delete mode 100644 shared/models/email_event/email_templates.ts delete mode 100644 shared/models/models.ts delete mode 100644 shared/models/session.model.ts delete mode 100644 shared/models/user.model.ts delete mode 100644 shared/routes/admin/admin.routes.ts delete mode 100644 shared/routes/auth.routes.ts delete mode 100644 shared/routes/emails.routes.ts delete mode 100644 shared/routes/user.routes.ts delete mode 100644 ui/app/(application)/admin/layout.tsx delete mode 100644 ui/app/(application)/admin/utilisateurs/[id]/components/UserView.tsx delete mode 100644 ui/app/(application)/admin/utilisateurs/[id]/page.tsx delete mode 100644 ui/app/(application)/admin/utilisateurs/components/UserList.tsx delete mode 100644 ui/app/(application)/admin/utilisateurs/page.tsx delete mode 100644 ui/app/(application)/auth/components/FormContainer.tsx delete mode 100644 ui/app/(application)/auth/connexion/page.tsx delete mode 100644 ui/app/(application)/auth/modifier-mot-de-passe/page.tsx delete mode 100644 ui/app/(application)/auth/mot-de-passe-oublie/page.tsx delete mode 100644 ui/app/(application)/cgu/components/Cgu.tsx delete mode 100644 ui/app/(application)/cgu/page.tsx delete mode 100644 ui/app/(application)/compte/profil/page.tsx delete mode 100644 ui/app/(application)/donnees-personnelles/components/DonneesPersonnelles.tsx delete mode 100644 ui/app/(application)/donnees-personnelles/page.tsx delete mode 100644 ui/app/(application)/mentions-legales/components/MentionLegales.tsx delete mode 100644 ui/app/(application)/mentions-legales/page.tsx delete mode 100644 ui/app/(application)/politique-confidentialite/components/PolitiqueConfidentialite.tsx delete mode 100644 ui/app/(application)/politique-confidentialite/page.tsx delete mode 100644 ui/app/(application)/sentry/page.tsx delete mode 100644 ui/context/AuthContext.tsx diff --git a/.bin/commands.sh b/.bin/commands.sh index 971e211..0e13c8b 100644 --- a/.bin/commands.sh +++ b/.bin/commands.sh @@ -10,13 +10,9 @@ function Help() { echo " release:interactive Build & Push Docker image releases" echo " release:app Build & Push Docker image releases" echo " deploy --user Deploy application to " - echo " preview:build Build preview" - echo " preview:cleanup --user Remove preview from close pull-requests" echo " vault:init Fetch initial vault-password from template-apprentissage" echo " vault:edit Edit vault file" echo " vault:password Show vault password" - echo " seed:update Update seed using a database" - echo " seed:apply Apply seed to a database" echo " deploy:log:encrypt Encrypt Github ansible logs" echo " deploy:log:dencrypt Decrypt Github ansible logs" echo @@ -47,18 +43,10 @@ function deploy() { "${SCRIPT_DIR}/deploy-app.sh" "$@" } -function preview:build() { - "${SCRIPT_DIR}/build-images.sh" "$@" -} - -function preview:cleanup() { - "${SCRIPT_DIR}/run-playbook.sh" "preview_cleanup.yml" "preview" -} - function vault:init() { # Ensure Op is connected - op account get > /dev/null - op document get ".vault-password-tmpl" --vault "mna-vault-passwords-common" > "${ROOT_DIR}/.infra/vault/.vault-password.gpg" + op --account mission-apprentissage account get > /dev/null + op --account mission-apprentissage document get ".vault-password-tmpl" --vault "mna-vault-passwords-common" > "${ROOT_DIR}/.infra/vault/.vault-password.gpg" } function vault:edit() { @@ -70,14 +58,6 @@ function vault:password() { "${SCRIPT_DIR}/get-vault-password-client.sh" "$@" } -function seed:update() { - "${SCRIPT_DIR}/seed-update.sh" "$@" -} - -function seed:apply() { - "${SCRIPT_DIR}/seed-apply.sh" "$@" -} - function deploy:log:encrypt() { (cd "$ROOT_DIR" && "${SCRIPT_DIR}/deploy-log-encrypt.sh" "$@") } diff --git a/.bin/scripts/build-images.sh b/.bin/scripts/build-images.sh index 568b3a2..ce71fe7 100755 --- a/.bin/scripts/build-images.sh +++ b/.bin/scripts/build-images.sh @@ -19,7 +19,7 @@ get_channel() { } if [[ $# == "0" ]]; then - echo "Veuillez spécifier les environnements à build (production, recette, preview, local)" + echo "Veuillez spécifier les environnements à build (production, recette, local)" exit 1; fi; diff --git a/.bin/scripts/deploy-app.sh b/.bin/scripts/deploy-app.sh index 766b55a..e108466 100755 --- a/.bin/scripts/deploy-app.sh +++ b/.bin/scripts/deploy-app.sh @@ -6,21 +6,7 @@ shift function deploy() { echo "Déploiement sur l'environnement ${ENV_FILTER}..." - - if [[ "$ENV_FILTER" == "preview" ]]; then - readonly PR_NUMBER=${1:?"Merci de préciser le numéro de la Pull Request (ex. 33)"}; - shift; - - if ! [[ $PR_NUMBER =~ ^[0-9]+$ ]]; then - echo "Merci de préciser le numéro de la Pull Request (ex. 33)" >&2; - echo "Usage: deploy-app.sh preview " >&2; - exit 1 - fi - - "${ROOT_DIR}/.bin/scripts/run-playbook.sh" "preview.yml" "$ENV_FILTER" --extra-var "pr_number=$PR_NUMBER" - else - "${ROOT_DIR}/.bin/scripts/run-playbook.sh" "deploy.yml" "$ENV_FILTER" "$@" - fi + "${ROOT_DIR}/.bin/scripts/run-playbook.sh" "deploy.yml" "$ENV_FILTER" "$@" } deploy "$@" diff --git a/.bin/scripts/get-vault-password-client.sh b/.bin/scripts/get-vault-password-client.sh index f1ef09d..7eec234 100755 --- a/.bin/scripts/get-vault-password-client.sh +++ b/.bin/scripts/get-vault-password-client.sh @@ -14,7 +14,7 @@ readonly VAULT_DIR="${ROOT_DIR}/.infra/vault" readonly VAULT_FILE="${VAULT_DIR}/vault.yml" readonly PRODUCT_NAME="tmpl" -DOCUMENT_CONTENT=$(op document get ".vault-password-${PRODUCT_NAME}" --vault "mna-vault-passwords-common" || echo "") +DOCUMENT_CONTENT=$(op --account mission-apprentissage document get ".vault-password-${PRODUCT_NAME}" --vault "mna-vault-passwords-common" || echo "") vault_password_file="${VAULT_DIR}/.vault-password.gpg" previous_vault_password_file="${VAULT_DIR}/.vault-password-previous.gpg" diff --git a/.bin/scripts/run-playbook.sh b/.bin/scripts/run-playbook.sh index 3a71cf0..f9ee55d 100755 --- a/.bin/scripts/run-playbook.sh +++ b/.bin/scripts/run-playbook.sh @@ -13,7 +13,7 @@ function runPlaybook() { local ansible_extra_opts=() if [[ -z "${ANSIBLE_BECOME_PASS:-}" ]]; then if [[ $* != *"pass"* ]]; then - local become_pass=$(op read op://Private/${PRODUCT_NAME}-$ENV_FILTER/password 2> /dev/null); + local become_pass=$(op --account mission-apprentissage read op://Private/${PRODUCT_NAME}-$ENV_FILTER/password 2> /dev/null); if [ -z $become_pass ]; then echo "Si vous avez 1password CLI, il est possible de récupérer le password automatiquement" echo "Pour cela, ajouter le dans le vault "Private" l'item ${PRODUCT_NAME}-$ENV_FILTER avec le champs password" @@ -29,7 +29,7 @@ function runPlaybook() { if [[ -z "${ANSIBLE_REMOTE_USER:-}" ]]; then if [[ $* != *"--user"* ]]; then - local username=$(op read op://Private/${PRODUCT_NAME}-$ENV_FILTER/username 2> /dev/null); + local username=$(op --account mission-apprentissage read op://Private/${PRODUCT_NAME}-$ENV_FILTER/username 2> /dev/null); if [ -z $username ]; then echo "Si vous avez 1password CLI, il est possible de récupérer le username automatiquement" echo "Pour cela, ajouter le dans le vault "Private" l'item ${PRODUCT_NAME}-$ENV_FILTER avec le champs username" diff --git a/.bin/scripts/seed-apply.sh b/.bin/scripts/seed-apply.sh deleted file mode 100755 index dc5861f..0000000 --- a/.bin/scripts/seed-apply.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if [ -z "${1:-}" ]; then - readonly TARGET_DB="mongodb://__system:password@localhost:27017/contrat?authSource=local&directConnection=true" -else - readonly TARGET_DB="$1" - shift -fi - -echo "base de donnée cible: $TARGET_DB" - -readonly SEED_GPG="$ROOT_DIR/.infra/files/configs/mongodb/seed.gpg" -readonly SEED_GZ="$ROOT_DIR/.infra/files/configs/mongodb/seed.gz" -readonly PASSPHRASE="$ROOT_DIR/.bin/SEED_PASSPHRASE.txt" -readonly VAULT_FILE="${ROOT_DIR}/.infra/vault/vault.yml" - -read -p "La base de donnée va etre écraser, voulez vous continuer ? [y/N]: " response -case $response in - [yY][eE][sS]|[yY]) - ;; - *) - exit 1 -;; -esac - -delete_cleartext() { - rm -f "$SEED_GZ" "$PASSPHRASE" -} -trap delete_cleartext EXIT - -ansible-vault view --vault-password-file="$ROOT_DIR/.bin/scripts/get-vault-password-client.sh" "$VAULT_FILE" | yq '.vault.SEED_GPG_PASSPHRASE' > "$PASSPHRASE" - -rm -f "$SEED_GZ" -gpg -d --batch --passphrase-file "$PASSPHRASE" -o "$SEED_GZ" "$SEED_GPG" -cat "$SEED_GZ" | docker compose -f "$ROOT_DIR/docker-compose.yml" exec -iT mongodb mongorestore --archive --nsInclude="${PRODUCT_NAME}.*" --uri="${TARGET_DB}" --drop --gzip - -yarn build:dev -yarn cli migrations:up -yarn cli indexes:recreate diff --git a/.bin/scripts/seed-update.sh b/.bin/scripts/seed-update.sh deleted file mode 100755 index 5068ba2..0000000 --- a/.bin/scripts/seed-update.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if [ -z "${1:-}" ]; then - readonly TARGET_DB="mongodb://__system:password@localhost:27017/?authSource=local&directConnection=true" -else - readonly TARGET_DB="$1" - shift -fi - -echo "base de donnée cible: $TARGET_DB" - -read -p "La base de donnée contient-elle des données sensible ? [Y/n]: " response -case $response in - [nN][oO]|[nN]) - ;; - *) - exit 1 -;; -esac - -readonly SEED_GPG="$ROOT_DIR/.infra/files/configs/mongodb/seed.gpg" -readonly SEED_GZ="$ROOT_DIR/.infra/files/configs/mongodb/seed.gz" -readonly PASSPHRASE="$ROOT_DIR/.bin/SEED_PASSPHRASE.txt" -readonly VAULT_FILE="${ROOT_DIR}/.infra/vault/vault.yml" - -delete_cleartext() { - rm -f "$SEED_GZ" "$PASSPHRASE" -} -trap delete_cleartext EXIT - -ansible-vault view --vault-password-file="$ROOT_DIR/.bin/scripts/get-vault-password-client.sh" "$VAULT_FILE" | yq '.vault.SEED_GPG_PASSPHRASE' > "$PASSPHRASE" - -docker compose -f "$ROOT_DIR/docker-compose.yml" up mongodb -d -mkdir -p "$ROOT_DIR/.infra/files/mongodb" - -yarn build:dev -yarn cli migrations:up -yarn cli indexes:recreate - -docker compose -f "$ROOT_DIR/docker-compose.yml" exec -it mongodb mongodump --uri "$TARGET_DB" --gzip --archive > "$SEED_GZ" -rm -f "$SEED_GPG" -gpg -c --cipher-algo twofish --batch --passphrase-file "$PASSPHRASE" -o "$SEED_GPG" "$SEED_GZ" diff --git a/.bin/scripts/setup-local-env.sh b/.bin/scripts/setup-local-env.sh index 341dd6a..fb6de53 100755 --- a/.bin/scripts/setup-local-env.sh +++ b/.bin/scripts/setup-local-env.sh @@ -24,11 +24,5 @@ echo "NEXT_PUBLIC_PRODUCT_NAME=\"${PRODUCT_NAME}\"" >> "${ROOT_DIR}/ui/.env" echo "NEXT_PUBLIC_PRODUCT_REPO=\"${REPO_NAME}\"" >> "${ROOT_DIR}/ui/.env" echo "NEXT_PUBLIC_API_PORT=5001" >> "${ROOT_DIR}/ui/.env" - yarn -chmod 400 "${ROOT_DIR}/.infra/local/mongo_keyfile" -yarn services:start -yarn setup:mongodb yarn build:dev -yarn cli migrations:up -yarn cli indexes:recreate diff --git a/.bin/zsh-completion b/.bin/zsh-completion index 9c361f2..3b447ce 100644 --- a/.bin/zsh-completion +++ b/.bin/zsh-completion @@ -10,13 +10,9 @@ _mna_completion() { "release\:app:'Build & Push Docker image releases'" "release\:interactive:'Interactivelly Build & Push Docker image releases'" "deploy:'Deploy application to '" - "preview\:build:'Build preview from open pull-requests'" - "preview\:cleanup:'Remove preview from close pull-requests'" "vault\:init:'Fetch initial vault-password from template-apprentissage'" "vault\:edit:'Edit vault file'" "vault\:password:'Get vault password'" - "seed\:update:'Update seed using a database'" - "seed\:apply:'Apply seed to a database'" "deploy\:log\:encrypt:'Encrypt Github ansible logs'" "deploy\:log\:dencrypt:'Decrypt Github ansible logs'" ) diff --git a/.gitattributes b/.gitattributes index abf43ca..c8d62f6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -77,4 +77,3 @@ *.otf binary *.woff binary *.woff2 binary -.infra/files/configs/mongodb/seed.gpg filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4eec991..dbf7572 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,13 +38,6 @@ jobs: - name: typecheck run: yarn typecheck:ci - - name: start mongodb service - run: | - chmod 400 .infra/local/mongo_keyfile - sudo chown 999:999 .infra/local/mongo_keyfile - docker compose up -d --wait mongodb - yarn setup:mongodb - - name: test run: yarn test:ci diff --git a/.github/workflows/deploy_preview.yml b/.github/workflows/deploy_preview.yml deleted file mode 100644 index 42b9800..0000000 --- a/.github/workflows/deploy_preview.yml +++ /dev/null @@ -1,162 +0,0 @@ -name: Deploy Preview -on: - issue_comment: - types: [created] - -jobs: - debug: - runs-on: ubuntu-latest - steps: - - uses: hmarr/debug-action@v2 - - deploy_preview: - if: (startsWith(github.event.comment.body, '🚀') || startsWith(github.event.comment.body, ':rocket:')) && github.event.issue.pull_request - concurrency: - group: ${{ github.workflow }}-${{ github.event.issue.id }} - cancel-in-progress: true - name: Deploy Preview ${{ github.event.issue.number }} - runs-on: ubuntu-latest - steps: - - name: Get Run URL - id: run_url - run: echo "url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - - - name: Comment PR Preview - if: github.event.issue.state != 'closed' - uses: thollander/actions-comment-pull-request@v2 - with: - message: | - ### :rocket: Prévisualisation - Deploying a new preview, follow progress in ${{ steps.run_url.outputs.url }} - comment_tag: deployment - mode: recreate - pr_number: ${{ github.event.issue.number }} - - - name: React to comment - uses: dkershner6/reaction-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commentId: ${{ github.event.comment.id }} - reaction: "+1" - - - id: "get-branch" - run: echo "branch=$(gh pr view $PR_NO --repo $REPO --json headRefName --jq '.headRefName')" >> $GITHUB_OUTPUT - env: - REPO: ${{ github.repository }} - PR_NO: ${{ github.event.issue.number }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ steps.get-branch.outputs.branch }} - - - name: Create LFS file list - run: git lfs ls-files --long | cut -d ' ' -f1 | sort > .lfs-assets-id - - - name: LFS Cache - uses: actions/cache@v4 - with: - path: .git/lfs/objects - key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }} - restore-keys: | - ${{ runner.os }}-lfs- - - - name: Git LFS Pull - run: git lfs pull - - - name: Install SSH key - uses: shimataro/ssh-key-action@v2 - with: - name: github_actions - key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} - known_hosts: ${{ vars.SSH_KNOWN_HOSTS }} - config: | - Host * - IdentityFile ~/.ssh/github_actions - - - name: Create vault pwd file - run: echo "${{ secrets.VAULT_PWD }}" > .infra/.vault_pwd.txt - - - name: Install jmespath - run: | - sudo pipx inject ansible-core jmespath - - - name: Run playbook - run: .bin/mna deploy preview "${{ github.event.issue.number }}" - env: - ANSIBLE_VAULT_PASSWORD_FILE: .infra/.vault_pwd.txt - ANSIBLE_REMOTE_USER: deploy - ANSIBLE_BECOME_PASS: ${{ secrets.DEPLOY_PASS }} - - - name: Encrypt logs - run: .bin/mna deploy:log:encrypt - if: always() - env: - ANSIBLE_VAULT_PASSWORD_FILE: .infra/.vault_pwd.txt - - - name: Upload logs artifacts - if: always() - uses: actions/upload-artifact@v4 - with: - name: logs-${{ github.event.issue.number }} - path: /tmp/deploy.log.gpg - - - name: Add Job summary - if: always() - run: echo 'You can get logs using `.bin/mna deploy:log:decrypt ${{ github.run_id }} ${{ github.event.issue.number }}`' >> $GITHUB_STEP_SUMMARY - - - name: Preview Summary when failed - if: failure() - run: echo 'You can get error logs using `.bin/mna deploy:log:decrypt ${{ github.run_id }}`' >> $GITHUB_STEP_SUMMARY - - - name: Preview Summary - run: echo 'https://${{ github.event.issue.number }}.${{ vars.app_name }}-preview.apprentissage.beta.gouv.fr/ 🚀' >> $GITHUB_STEP_SUMMARY - - - name: Comment PR Preview - if: github.event.issue.state != 'closed' - uses: thollander/actions-comment-pull-request@v2 - with: - message: | - ### :rocket: Prévisualisation - https://${{ github.event.issue.number }}.${{ vars.app_name }}-preview.apprentissage.beta.gouv.fr/ - - You can access runner logs in ${{ steps.run_url.outputs.url }} - - To re-deploy just add a comment with :rocket: - comment_tag: deployment - mode: recreate - pr_number: ${{ github.event.issue.number }} - - - name: Comment PR Preview when failed - if: failure() && github.event.issue.state != 'closed' - uses: thollander/actions-comment-pull-request@v2 - with: - message: | - ### :ambulance: Prévisualisation failed - - https://${{ github.event.issue.number }}.${{ vars.app_name }}-preview.apprentissage.beta.gouv.fr/ - - You can get error logs using `.bin/mna deploy:log:decrypt ${{ github.run_id }}` - You can access runner logs in ${{ steps.run_url.outputs.url }} - - To re-deploy just add a comment with :rocket: - comment_tag: deployment - mode: recreate - pr_number: ${{ github.event.issue.number }} - - - name: Comment PR Preview when cancelled - if: cancelled() && github.event.issue.state != 'closed' - uses: thollander/actions-comment-pull-request@v2 - with: - message: | - ### :ambulance: Prévisualisation cancelled - - https://${{ github.event.issue.number }}.${{ vars.app_name }}-preview.apprentissage.beta.gouv.fr/ - - You can access runner logs in ${{ steps.run_url.outputs.url }} - - To re-deploy just add a comment with :rocket: - comment_tag: deployment - mode: recreate - pr_number: ${{ github.event.issue.number }} diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml deleted file mode 100644 index f48857a..0000000 --- a/.github/workflows/preview.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: PR CI and Preview -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review, closed] - -jobs: - tests: - if: github.event.pull_request.state == 'open' - uses: "./.github/workflows/ci.yml" - - deploy_comment: - name: Add deploy comment - runs-on: ubuntu-latest - steps: - - name: Comment PR Preview - if: github.event.pull_request.state != 'closed' - uses: thollander/actions-comment-pull-request@v2 - with: - message: | - To deploy this PR just add a comment with a simple :rocket: - comment_tag: deployment_instructions - mode: upsert diff --git a/.github/workflows/preview_cleanup.yml b/.github/workflows/preview_cleanup.yml deleted file mode 100644 index a17107b..0000000 --- a/.github/workflows/preview_cleanup.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Clean Previews -on: - schedule: - - cron: "0 0 * * *" - -concurrency: - group: ${{ github.workflow }} - -jobs: - cleanup: - name: Clean Previews - runs-on: ubuntu-latest - steps: - - name: Checkout project - uses: actions/checkout@v4 - with: - lfs: true - - - name: Install SSH key - uses: shimataro/ssh-key-action@v2 - with: - name: github_actions - key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} - known_hosts: ${{ vars.SSH_KNOWN_HOSTS }} - config: | - Host * - IdentityFile ~/.ssh/github_actions - - - name: Create vault pwd file - run: echo ${{ secrets.VAULT_PWD }} > .infra/.vault_pwd.txt - - - name: Install jmespath - run: | - sudo pipx inject ansible-core jmespath - - - name: Run playbook - run: .bin/mna preview:cleanup - env: - ANSIBLE_VAULT_PASSWORD_FILE: .infra/.vault_pwd.txt - ANSIBLE_REMOTE_USER: deploy - ANSIBLE_BECOME_PASS: ${{ secrets.DEPLOY_PASS }} diff --git a/.gitignore b/.gitignore index f6ac4ae..42383e3 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,6 @@ yarn-error.log* # Runtime data pids *.pid -*.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover @@ -161,7 +160,6 @@ vault-tmp-*.* ui/next-env.d.ts SEED_PASSPHRASE.txt -seed.gz tsconfig.tsbuildinfo diff --git a/.infra/.env_server b/.infra/.env_server index 09654c2..cbe5f75 100644 --- a/.infra/.env_server +++ b/.infra/.env_server @@ -6,19 +6,5 @@ LOG_TYPE={{ vault[env_type].LOG_TYPE }} LOG_LEVEL=info # Sentry SENTRY_DSN={{ vault.SERVER_SENTRY_DSN }} -# MongoDb -MONGODB_URI={{ vault[env_type].MONGODB_URI }} -# Auth -AUTH_USER_JWT_SECRET={{ vault[env_type].AUTH_USER_JWT_SECRET }} -AUTH_PASSWORD_JWT_SECRET={{ vault[env_type].AUTH_PASSWORD_JWT_SECRET }} -SESSION_SECRET={{ vault[env_type].SESSION_SECRET }} -AUTH_HASH_ROUNDS={{ vault[env_type].AUTH_HASH_ROUNDS }} -# SMTP -EMAIL={{vault.EMAIL}} -SMTP_HOST={{ vault[env_type].SMTP_HOST }} -SMTP_PORT={{ vault[env_type].SMTP_PORT }} -SMTP_WEBHOOK_KEY={{ vault[env_type].SMTP_WEBHOOK_KEY }} -SMTP_AUTH_USER={{ vault[env_type].SMTP_AUTH_USER }} -SMTP_AUTH_PASS={{ vault[env_type].SMTP_AUTH_PASS }} # API ENTREPRISE MNA_CONTRAT_API_ENTREPRISE_SECRET={{ vault.MNA_CONTRAT_API_ENTREPRISE_SECRET }} diff --git a/.infra/.gitignore b/.infra/.gitignore index 44d06e7..956ff39 100644 --- a/.infra/.gitignore +++ b/.infra/.gitignore @@ -30,7 +30,6 @@ yarn-error.log* # Runtime data pids *.pid -*.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover diff --git a/.infra/ansible/deploy.yml b/.infra/ansible/deploy.yml index fc19dff..e9a9b64 100644 --- a/.infra/ansible/deploy.yml +++ b/.infra/ansible/deploy.yml @@ -18,52 +18,6 @@ cmd: docker stack ls --format json register: stack_status - - name: Récupération du status des migrations - shell: - chdir: /opt/app - cmd: "sudo /opt/app/scripts/migrations-status.sh" - register: migration_status_output - when: stack_status.stdout != "" - - - name: "Shutdown processor" - shell: - chdir: /opt/app - cmd: "sudo docker service scale {{product_name}}_jobs_processor=0" - when: - - stack_status.stdout != "" - - '"migrations-status=synced" not in migration_status_output.stdout_lines' - - - name: "Activation du mode maintenance pour effectuer la migration" - shell: - chdir: /opt/app - cmd: "sudo /opt/app/tools/maintenance/maintenance-on.sh" - when: - - stack_status.stdout != "" - - '"migrations-status=synced" not in migration_status_output.stdout_lines' - - - name: "Shutdown server" - shell: - chdir: /opt/app - cmd: "sudo docker service scale {{product_name}}_server=0" - when: - - stack_status.stdout != "" - - '"migrations-status=synced" not in migration_status_output.stdout_lines' - - - name: Lancement des migrations - shell: - chdir: /opt/app - cmd: "sudo /opt/app/scripts/migrations-up.sh" - when: - - stack_status.stdout != "" - - '"migrations-status=synced" not in migration_status_output.stdout_lines' - async: 1800 - poll: 10 - - - name: Trigger de la création des indexes - shell: - chdir: /opt/app - cmd: "sudo /opt/app/scripts/trigger-indexes-creation.sh" - - name: Lancement de l'application {{env_type}} shell: chdir: /opt/app @@ -97,12 +51,6 @@ chdir: /opt/app cmd: "sudo /opt/app/tools/ssl/renew-certificate.sh {{dns_name}}" - - name: "Setup de la Metabase" - shell: - chdir: /opt/app - cmd: "sudo bash /opt/app/configs/metabase/setup-metabase.sh" - timeout: 86400 # 1 day - - name: "Prune Docker" shell: chdir: /opt/app diff --git a/.infra/ansible/preview.yml b/.infra/ansible/preview.yml deleted file mode 100644 index 24a2338..0000000 --- a/.infra/ansible/preview.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -- hosts: preview - become: true - gather_facts: false - vars_files: - - "../vault/vault.yml" - tasks: - - include_tasks: ./tasks/files_copy.yml - - - name: lancement preview system - shell: - chdir: /opt/app - cmd: docker compose -f docker-compose.preview-system.yml up -d --wait - - - name: Setup MongoDB ReplicaSet - shell: - chdir: /opt/app - cmd: 'docker compose -f docker-compose.preview-system.yml exec -it mongodb mongosh "{{ vault[env_type].MONGODB_URI }}" --eval "try { rs.status().ok } catch (e) { if (e.code === 94) {rs.initiate();} else {throw e} }" --quiet' - when: env_type == 'preview' - - - include_tasks: ./tasks/preview_pr.yml - vars: - build: true - docker_images: - - "mna_{{product_name}}_ui" - - "mna_{{product_name}}_server" diff --git a/.infra/ansible/preview_cleanup.yml b/.infra/ansible/preview_cleanup.yml deleted file mode 100644 index 9d49fec..0000000 --- a/.infra/ansible/preview_cleanup.yml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- hosts: preview - become: true - gather_facts: false - vars_files: - - "../vault/vault.yml" - tasks: - - name: List projects - ansible.builtin.find: - paths: /opt/app/projects - file_type: directory - register: projects - - - include_tasks: ./tasks/preview_pr.yml - loop: "{{ projects.files | map(attribute='path')| map('basename') | list }}" - loop_control: - loop_var: pr_number - vars: - build: false - docker_images: - - "mna_{{product_name}}_ui" - - "mna_{{product_name}}_server" - - - name: Prune Docker Containers - shell: - cmd: docker container prune --force - - - name: Prune Docker Images - shell: - cmd: docker image prune --all --force - - - name: Prune Docker Volumes - shell: - cmd: docker volume prune diff --git a/.infra/ansible/tasks/files_copy.yml b/.infra/ansible/tasks/files_copy.yml index 2061282..6ecca35 100644 --- a/.infra/ansible/tasks/files_copy.yml +++ b/.infra/ansible/tasks/files_copy.yml @@ -21,37 +21,16 @@ - item.state == 'file' - item.path | basename != '.gitkeep' - item.path | basename != '.DS_Store' - # seed.gpg should not be template replaced - - item.path | basename != 'seed.gpg' - - item.path | basename != 'mongo_keyfile.txt' - - item.path | basename != 'seed.gz' # /app/tools is managed by infra - item.path | regex_search('^tools/?') == none - item.path | regex_search('^system/?') == none -- name: Copie du fichier de seed - ansible.builtin.copy: - src: "{{inventory_dir}}/files/configs/mongodb/seed.gpg" - dest: "/opt/app/configs/mongodb/seed.gpg" - mode: "700" - when: env_type == 'preview' - -- name: Copie du fichier mongodb keyfile - ansible.builtin.template: - src: "{{inventory_dir}}/files/configs/mongodb/mongo_keyfile.txt" - dest: "/opt/app/configs/mongodb/mongo_keyfile.txt" - mode: "400" - owner: 999 - group: 999 - when: env_type == 'preview' - - name: copy server env file ansible.builtin.template: src: "{{ item }}" dest: "/opt/app/.env_server" with_fileglob: - "{{inventory_dir}}/.env_server" - when: env_type != 'preview' - name: copy ui env file ansible.builtin.template: @@ -59,7 +38,6 @@ dest: "/opt/app/.env_ui" with_fileglob: - "{{inventory_dir}}/.env_ui" - when: env_type != 'preview' - name: copy du fichier docker compose ansible.builtin.template: @@ -67,18 +45,8 @@ dest: "/opt/app/docker-compose.production.yml" with_fileglob: - "{{inventory_dir}}/docker-compose.production.yml" - when: env_type != 'preview' - name: copy du fichier recette docker compose - ansible.builtin.template: - src: "{{ item }}" - dest: "/opt/app/docker-compose.recette.yml" - with_fileglob: - - "{{inventory_dir}}/docker-compose.recette.yml" - when: env_type == 'recette' - -- name: creation du fichier docker compose preview system - ansible.builtin.template: - src: "{{inventory_dir}}/docker-compose.preview-system.yml" - dest: "/opt/app/docker-compose.preview-system.yml" - when: env_type == 'preview' + ansible.builtin.file: + path: "/opt/app/docker-compose.recette.yml" + state: absent diff --git a/.infra/ansible/tasks/preview_pr.yml b/.infra/ansible/tasks/preview_pr.yml deleted file mode 100644 index 03ad6d6..0000000 --- a/.infra/ansible/tasks/preview_pr.yml +++ /dev/null @@ -1,133 +0,0 @@ ---- -- name: "[{{ pr_number }}] Get Pull Request Infos" - ansible.builtin.shell: curl -s https://api.github.com/repos/mission-apprentissage/{{repo_name}}/pulls/{{ pr_number }} - register: result - -- name: "[{{ pr_number }}] Save Pull Requests Infos" - set_fact: - pr_commit_id: "{{ result.stdout | from_json | json_query('head.sha') }}" - pr_title: "{{ result.stdout | from_json | json_query('title') }}" - pr_state: "{{ result.stdout | from_json | json_query('state') }}" - -- name: "[{{ pr_number }}] Deploying preview" - when: - - pr_state == 'open' - - build == true - block: - - name: "[{{ pr_number }}] création du répertoire de build" - file: - path: /opt/app/projects/{{ pr_number }} - state: directory - owner: root - group: root - mode: 770 - - - name: "[{{ pr_number }}] copy server env file" - ansible.builtin.copy: - content: "{{ lookup('ansible.builtin.template', '../.env_server') }}" - dest: "/opt/app/projects/{{ pr_number }}/.env_server" - - - name: "[{{ pr_number }}] copy ui env file" - ansible.builtin.copy: - content: "{{ lookup('ansible.builtin.template', '../.env_ui') }}" - dest: "/opt/app/projects/{{ pr_number }}/.env_ui" - - - name: "[{{ pr_number }}] creation du fichier docker compose" - ansible.builtin.template: - src: "{{inventory_dir}}/docker-compose.preview.yml" - dest: "/opt/app/projects/{{ pr_number }}/docker-compose.yml" - - - name: "Check if repository exists" - stat: - path: "/opt/app/projects/{{ pr_number }}/repository" - register: check_stat - - - name: "Pruning repository references" - shell: - chdir: "/opt/app/projects/{{ pr_number }}/repository" - cmd: git remote prune origin - when: check_stat.stat.exists - - - name: "[{{ pr_number }}] Clone du repository" - git: - repo: "git@github.com:mission-apprentissage/{{repo_name}}.git" - version: "{{ pr_commit_id }}" - force: yes - accept_newhostkey: yes - dest: "/opt/app/projects/{{ pr_number }}/repository" - - - name: "[{{ pr_number }}] Root only pour tous les répertoires applicatifs" - file: - path: "{{item}}" - state: directory - owner: root - group: root - mode: 770 - with_items: - - "/opt/app/projects/{{ pr_number }}/repository" - - - name: "[{{ pr_number }}] Build local images 0.0.0-{{ pr_number }}" - shell: - cmd: "flock --verbose --close /tmp/deployment_build.lock .bin/mna preview:build 0.0.0-{{ pr_number }} load preview" - chdir: "/opt/app/projects/{{ pr_number }}/repository" - async: 900 # max 15 minutes - poll: 15 # check every 15s - - - name: "[{{ pr_number }}] Start Application" - shell: - chdir: "/opt/app/projects/{{ pr_number }}" - cmd: docker compose up -d --remove-orphans --wait - - - name: "[{{ pr_number }}] Trigger ACME companion" - shell: - chdir: /opt/app - cmd: docker exec nginx-proxy-acme /app/signal_le_service - - - name: "[{{ pr_number }}] Seed database" - shell: - chdir: "/opt/app" - cmd: "flock --verbose --close /tmp/deployment_seed.lock /opt/app/scripts/seed.sh preview_{{ pr_number | default('00') }}" - async: 900 # max 15 minutes - poll: 15 # check every 15s - - - name: "[{{ pr_number }}] Execute MongoDB migrations" - shell: - chdir: "/opt/app/projects/{{ pr_number }}" - cmd: "docker compose run --rm server yarn cli migrations:up" - - - name: "[{{ pr_number }}] Preview URL" - debug: - msg: "{{ vault[env_type].PUBLIC_URL }}" - -- name: "[{{ pr_number }}] Uninstalling preview" - when: pr_state != 'open' - block: - - name: "[{{ pr_number }}] Check if preview is deployed" - stat: - path: "/opt/app/projects/{{ pr_number }}" - register: check_stat - - - name: "[{{ pr_number }}] Stopping the preview" - shell: - chdir: "/opt/app/projects/{{ pr_number }}" - cmd: docker compose down --remove-orphans --volumes - when: check_stat.stat.exists - ignore_errors: true - - - name: "[{{ pr_number }}] Removing {{ item }}:0.0.0-{{ pr_number }} image" - shell: - cmd: "docker image rm -f ghcr.io/mission-apprentissage/{{ item }}:0.0.0-{{ pr_number }}" - when: check_stat.stat.exists - loop: "{{ docker_images }}" - - - name: "[{{ pr_number }}] Remove database" - shell: - cmd: docker run --rm -i --network mna_network mongo:6.0.2-focal mongosh "{{ vault[env_type].MONGODB_URI }}" --eval "db.dropDatabase()" - - - name: "[{{ pr_number }}] Removing preview directory" - shell: - cmd: "rm -rf /opt/app/projects/{{ pr_number }}" - when: check_stat.stat.exists - - - name: "[{{ pr_number }}] Clean Docker" - shell: docker system prune --force --volumes diff --git a/.infra/docker-compose.preview-system.yml b/.infra/docker-compose.preview-system.yml deleted file mode 100644 index f556b43..0000000 --- a/.infra/docker-compose.preview-system.yml +++ /dev/null @@ -1,148 +0,0 @@ -version: "3.8" - -x-default: &default - deploy: - resources: - limits: - memory: 1g - restart: always - networks: - - mna_network - -name: "{{product_name}}_preview_system" - -services: - reverse_proxy: - <<: *default - image: "nginxproxy/nginx-proxy" - container_name: "{{product_name}}_reverse_proxy" - ports: - - "80:80" - - "443:443" - volumes: - - conf:/etc/nginx/conf.d - - vhost:/etc/nginx/vhost.d - - html:/usr/share/nginx/html - - certs:/etc/nginx/certs:ro - - /var/run/docker.sock:/tmp/docker.sock:ro - labels: - - autoheal=true - - acme-companion: - <<: *default - image: nginxproxy/acme-companion - container_name: nginx-proxy-acme - volumes: - - certs:/etc/nginx/certs:rw - - acme:/etc/acme.sh - - /var/run/docker.sock:/var/run/docker.sock:ro - environment: - - DEFAULT_EMAIL=misson.apprentissage.devops@gmail.com - volumes_from: - - reverse_proxy - - mongodb: - <<: *default - image: mongo:6.0.2-focal - hostname: mongodb - container_name: "{{product_name}}_mongodb" - deploy: - resources: - limits: - memory: 2g - ports: - - "127.0.0.1:27017:27017" - command: ["-f", "/etc/mongod/mongod.conf"] - volumes: - - /opt/app/data/mongodb/db:/data/db - - /opt/app/configs/mongodb:/etc/mongod - healthcheck: - test: ["CMD", "mongosh", "--eval", '''db.runCommand("ping").ok''', "--quiet"] - interval: 10s - timeout: 5s - retries: 12 - start_period: 10s - labels: - - autoheal=true - - smtp: - <<: *default - image: axllent/mailpit:v1.5.5 - container_name: "{{product_name}}_smtp" - ports: - - 1025:1025 - volumes: - - /opt/app/data/smtp:/data - - /opt/app/configs/mailpit/auth:/auth - environment: - - MP_DATA_FILE=/data/mailpit.db - - MP_UI_AUTH_FILE=/auth/auth - - VIRTUAL_HOST=smtp.{{dns_name}} - - VIRTUAL_PATH=/ - - VIRTUAL_PORT=8025 - - LETSENCRYPT_HOST=smtp.{{dns_name}} - - LETSENCRYPT_EMAIL=misson.apprentissage.devops@gmail.com - - nodeexporter: - <<: *default - image: prom/node-exporter:v1.5.0 - hostname: "{{host_name}}" - user: root - command: - - "--path.procfs=/host/proc" - - "--path.rootfs=/rootfs" - - "--path.sysfs=/host/sys" - - "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)" - - "--collector.textfile.directory=/var/cron-exporter" - volumes: - - /proc:/host/proc:ro - - /sys:/host/sys:ro - - /:/rootfs:ro - - /opt/app/system/cron:/var/cron-exporter:rw - environment: - - VIRTUAL_HOST={{dns_name}} - - VIRTUAL_DEST=/metrics - - VIRTUAL_PATH=/_monitoring/nodeexporter - - VIRTUAL_PORT=9100 - - LETSENCRYPT_HOST={{dns_name}} - - LETSENCRYPT_EMAIL=misson.apprentissage.devops@gmail.com - - cadvisor: - <<: *default - image: gcr.io/cadvisor/cadvisor:v0.46.0 - hostname: "{{host_name}}" - privileged: true - devices: - - /dev/kmsg - volumes: - - /:/rootfs:ro - - /var/run:/var/run:ro - - /sys:/sys:ro - - /var/lib/docker/:/var/lib/docker:ro - - /dev/disk/:/dev/disk:ro - environment: - - VIRTUAL_HOST={{dns_name}} - - VIRTUAL_DEST=/metrics - - VIRTUAL_PATH=/_monitoring/cadvisor - - VIRTUAL_PORT=8080 - - LETSENCRYPT_HOST={{dns_name}} - - LETSENCRYPT_EMAIL=misson.apprentissage.devops@gmail.com - - autoheal: - <<: *default - image: willfarrell/autoheal:latest - container_name: "{{product_name}}_autoheal" - volumes: - - /var/run/docker.sock:/var/run/docker.sock - -volumes: - conf: - vhost: - html: - certs: - acme: - -networks: - mna_network: - name: mna_network - external: true diff --git a/.infra/docker-compose.preview.yml b/.infra/docker-compose.preview.yml deleted file mode 100644 index 05b9a71..0000000 --- a/.infra/docker-compose.preview.yml +++ /dev/null @@ -1,70 +0,0 @@ -version: "3.8" - -x-deploy-default: &deploy-default - resources: - limits: - memory: 2g - -x-default: &default - deploy: - <<: *deploy-default - restart: always - networks: - - mna_network - -name: "{{product_name}}_preview_{{pr_number}}" - -services: - server: - <<: *default - image: "ghcr.io/mission-apprentissage/mna_{{product_name}}_server:0.0.0-{{pr_number}}" - container_name: "{{product_name}}_{{pr_number}}_server" - environment: - - VIRTUAL_HOST={{pr_number}}.{{domain_name}}-preview.apprentissage.beta.gouv.fr - - VIRTUAL_PATH=/api - - VIRTUAL_PORT=5000 - - LETSENCRYPT_HOST={{pr_number}}.{{domain_name}}-preview.apprentissage.beta.gouv.fr - - LETSENCRYPT_EMAIL=misson.apprentissage.devops@gmail.com - env_file: .env_server - volumes: - - server:/data - stop_grace_period: 30s - healthcheck: - test: ["CMD", "curl", "--fail", "http://localhost:5000/api/healthcheck"] - interval: 10s - timeout: 30s - retries: 11 - start_period: 10s - labels: - - autoheal=true - - ui: - <<: *default - image: "ghcr.io/mission-apprentissage/mna_{{product_name}}_ui:0.0.0-{{pr_number}}-preview" - container_name: "{{product_name}}_{{pr_number}}_ui" - env_file: .env_ui - stop_grace_period: 30s - environment: - - VIRTUAL_HOST={{pr_number}}.{{domain_name}}-preview.apprentissage.beta.gouv.fr - - VIRTUAL_PATH=/ - - VIRTUAL_PORT=3000 - - LETSENCRYPT_HOST={{pr_number}}.{{domain_name}}-preview.apprentissage.beta.gouv.fr - - LETSENCRYPT_EMAIL=misson.apprentissage.devops@gmail.com - - processor: - <<: *default - image: "ghcr.io/mission-apprentissage/mna_{{product_name}}_server:0.0.0-{{pr_number}}" - container_name: "{{product_name}}_{{pr_number}}_jobs_processor" - command: ["yarn", "cli", "processor"] - env_file: .env_server - stop_grace_period: 900s - volumes: - - server:/data - -volumes: - server: - -networks: - mna_network: - name: mna_network - external: true diff --git a/.infra/docker-compose.production.yml b/.infra/docker-compose.production.yml index e7d49b9..9fc084f 100644 --- a/.infra/docker-compose.production.yml +++ b/.infra/docker-compose.production.yml @@ -1,5 +1,3 @@ -version: "3.8" - # The following variables define reusable configurations for deployment, providing consistent and predefined # behaviors for updating, rolling back, and restarting services. @@ -48,27 +46,6 @@ services: retries: 11 start_period: 10s - jobs_processor: - <<: *default - image: ghcr.io/mission-apprentissage/mna_{{product_name}}_server:{{app_version}} - deploy: - <<: *deploy-default - resources: - limits: - memory: 2g - replicas: 2 - command: ["yarn", "cli", "job_processor:start"] - env_file: .env_server - stop_grace_period: 2h - volumes: - - /opt/app/data/server:/data - logging: - driver: "fluentd" - options: - fluentd-address: localhost:24224 - tag: docker.json.{{product_name}}.{{env_type}}.jobs_processor - fluentd-async: "true" - ui: <<: *default image: ghcr.io/mission-apprentissage/mna_{{product_name}}_ui:{{app_version}}-{{env_type}} @@ -86,40 +63,3 @@ services: fluentd-address: localhost:24224 tag: docker.txt.{{product_name}}.{{env_type}}.ui fluentd-async: "true" - - metabase: - <<: *default - image: metabase/metabase:v0.46.6.4 - deploy: - <<: *deploy-default - resources: - limits: - memory: 2g - environment: - JAVA_TIMEZONE: Europe/Paris - MB_SITE_LOCALE: fr - MB_SITE_URL: "{{dns_name}}/metabase" - MB_DB_TYPE: postgres - MB_DB_CONNECTION_URI: "{{vault[env_type].METABASE_DB_URI}}" - MB_ENCRYPTION_SECRET_KEY: "{{vault[env_type].METABASE_ENCRYPTION_SECRET_KEY}}" - MB_EMAIL_FROM_ADDRESS: "{{vault.METABASE_EMAIL_FROM_ADDRESS}}" - MB_EMAIL_FROM_NAME: "{{vault.METABASE_EMAIL_FROM_NAME}}" - MB_PASSWORD_COMPLEXITY: strong - MB_START_OF_WEEK: monday - MB_EMAIL_SMTP_HOST: "{{vault[env_type].SMTP_HOST}}" - MB_EMAIL_SMTP_PORT: "{{vault[env_type].SMTP_PORT}}" - MB_EMAIL_SMTP_USERNAME: "{{vault[env_type].SMTP_AUTH_USER}}" - MB_EMAIL_SMTP_PASSWORD: "{{vault[env_type].SMTP_AUTH_PASS}}" - MB_EMAIL_SMTP_SECURITY: tls - healthcheck: - test: curl --fail -I http://localhost:3000/api/health || exit 1 - interval: 15s - timeout: 5s - retries: 5 - start_period: 6m - logging: - driver: "fluentd" - options: - fluentd-address: localhost:24224 - tag: docker.json.{{product_name}}.{{env_type}}.metabase - fluentd-async: "true" diff --git a/.infra/docker-compose.recette.yml b/.infra/docker-compose.recette.yml deleted file mode 100644 index 66c0c27..0000000 --- a/.infra/docker-compose.recette.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: "3.8" - -services: - smtp: - image: axllent/mailpit:latest - deploy: - resources: - limits: - memory: 128m - update_config: - failure_action: rollback - parallelism: 1 - delay: 10s - rollback_config: - parallelism: 1 - delay: 10s - restart_policy: - window: 360s - delay: 30s - # Max 24hours - max_attempts: 240 - ports: - - 1025:1025 - - 8025:8025 - networks: - - mna_network - volumes: - - /opt/app/data/smtp:/data - - /opt/app/configs/mailpit/auth:/auth - environment: - - MP_DATA_FILE=/data/mailpit.db - - MP_UI_AUTH_FILE=/auth - logging: - driver: "fluentd" - options: - fluentd-address: localhost:24224 - tag: docker.json.{{product_name}}.{{env_type}}.smtp - fluentd-async: "true" diff --git a/.infra/env.ini b/.infra/env.ini index 26713d3..c2923b4 100644 --- a/.infra/env.ini +++ b/.infra/env.ini @@ -19,13 +19,6 @@ dns_name={{domain_name}}-recette.apprentissage.beta.gouv.fr host_name={{product_name}}-recette env_type=recette -[preview] -51.68.44.237 -[preview:vars] -dns_name={{domain_name}}-preview.apprentissage.beta.gouv.fr -host_name={{product_name}}-preview -env_type=preview - [local] localhost ansible_host=127.0.0.1 ansible_connection=local [local:vars] diff --git a/.infra/files/configs/mailpit/.gitkeep b/.infra/files/configs/mailpit/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/.infra/files/configs/mailpit/auth b/.infra/files/configs/mailpit/auth deleted file mode 100644 index 8d40398..0000000 --- a/.infra/files/configs/mailpit/auth +++ /dev/null @@ -1 +0,0 @@ -user:$2y$05$u9jmotshh4BQBZXSkBgFh.iLei0r2XTHqxZ5SESVOBGXW85gvClMO diff --git a/.infra/files/configs/metabase/setup-metabase.sh b/.infra/files/configs/metabase/setup-metabase.sh deleted file mode 100755 index 8760108..0000000 --- a/.infra/files/configs/metabase/setup-metabase.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -PROPS=$(curl -sS --retry 5 --retry-all-errors https://{{dns_name}}/metabase/api/session/properties) -IS_SETUP=$(echo $PROPS | jq -r '."has-user-setup"') - -if [[ $IS_SETUP == "true" ]]; then - echo 'metabase already setup' - exit 0; -fi - -TOKEN=$(echo $PROPS | jq -r '."setup-token"') - -curl -sS --retry 5 --retry-all-errors https://{{dns_name}}/metabase/api/setup \ ---header 'Content-Type: application/json' \ ---data-raw "{ - \"token\": \"$TOKEN\", - \"user\": { - \"password_confirm\": \"{{ vault[env_type].METABASE_ADMIN_PASS }}\", - \"password\": \"{{ vault[env_type].METABASE_ADMIN_PASS }}\", - \"site_name\": \"{{product_name}}\", - \"email\": \"{{ vault[env_type].METABASE_ADMIN_EMAIL }}\", - \"last_name\": null, - \"first_name\": null - }, - \"database\": { - \"is_on_demand\": false, - \"is_full_sync\": false, - \"is_sample\": false, - \"cache_ttl\": null, - \"refingerprint\": false, - \"auto_run_queries\": true, - \"schedules\": {}, - \"details\": { - \"use-conn-uri\": true, - \"conn-uri\": \"{{ vault[env_type].MONGODB_METABASE_URI }}\", - \"tunnel-enabled\": false, - \"advanced-options\": true, - \"ssl\": true - }, - \"name\": \"MongoDB\", - \"engine\": \"mongo\" - }, - \"invite\": null, - \"prefs\": { - \"site_name\": \"{{product_name}}\", - \"site_locale\": \"fr\", - \"allow_tracking\": false - } -}" - -echo 'metabase setup successfully' diff --git a/.infra/files/configs/mongodb/mongo_keyfile.txt b/.infra/files/configs/mongodb/mongo_keyfile.txt deleted file mode 100644 index c8a94c4..0000000 --- a/.infra/files/configs/mongodb/mongo_keyfile.txt +++ /dev/null @@ -1 +0,0 @@ -{{vault.MONGODB_KEYFILE}} diff --git a/.infra/files/configs/mongodb/mongod.conf b/.infra/files/configs/mongodb/mongod.conf deleted file mode 100644 index 84d9216..0000000 --- a/.infra/files/configs/mongodb/mongod.conf +++ /dev/null @@ -1,8 +0,0 @@ -net: - bindIpAll: true - -replication: - replSetName: replica - -security: - keyFile: /etc/mongod/mongo_keyfile.txt diff --git a/.infra/files/configs/mongodb/seed.gpg b/.infra/files/configs/mongodb/seed.gpg deleted file mode 100644 index 232f831..0000000 --- a/.infra/files/configs/mongodb/seed.gpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:988b46c23bb43acba2321dc1e19f9d5c2e54eebe6d43e2f81876379982130359 -size 3007 diff --git a/.infra/files/configs/reverse_proxy/locations/70_smtp.conf.template b/.infra/files/configs/reverse_proxy/locations/70_smtp.conf.template deleted file mode 100644 index 1d0f29b..0000000 --- a/.infra/files/configs/reverse_proxy/locations/70_smtp.conf.template +++ /dev/null @@ -1,8 +0,0 @@ -location ~ ^/smtp/(.*)$ { - set $upstream http://smtp:8025; - proxy_pass $upstream/$1$is_args$args; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Forwarded-Proto $scheme; -} diff --git a/.infra/files/configs/reverse_proxy/locations/80_metabase.conf.template b/.infra/files/configs/reverse_proxy/locations/80_metabase.conf.template deleted file mode 100644 index f24f141..0000000 --- a/.infra/files/configs/reverse_proxy/locations/80_metabase.conf.template +++ /dev/null @@ -1,8 +0,0 @@ -location ~ ^/metabase/(.*)$ { - set $upstream http://metabase:3000; - proxy_pass $upstream/$1$is_args$args; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Forwarded-Proto $scheme; -} diff --git a/.infra/files/data/smtp/.gitkeep b/.infra/files/data/smtp/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/.infra/files/scripts/migrations-status.sh b/.infra/files/scripts/migrations-status.sh deleted file mode 100755 index c418bd8..0000000 --- a/.infra/files/scripts/migrations-status.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -#Needs to be run as sudo - -/opt/app/tools/docker-compose.sh run --rm --no-deps server yarn cli migrations:status diff --git a/.infra/files/scripts/migrations-up.sh b/.infra/files/scripts/migrations-up.sh deleted file mode 100755 index f569d34..0000000 --- a/.infra/files/scripts/migrations-up.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -#Needs to be run as sudo - -readonly LOG_DIR="/var/log/data-jobs" -readonly LOG_FILEPATH="${LOG_DIR}/run-migrations_$(date +'%Y-%m-%d_%H%M%S').log" - -if [ ! -d "$LOG_DIR" ]; then - sudo mkdir -p "$LOG_DIR" - sudo chown $(whoami):$(whoami) "$LOG_DIR" -fi - -run_migrations(){ - echo "Application des migrations ..." - /opt/app/tools/docker-compose.sh run --rm --no-deps server yarn cli migrations:up 2>&1 | tee "$LOG_FILEPATH" -} - -run_migrations diff --git a/.infra/files/scripts/seed.sh b/.infra/files/scripts/seed.sh deleted file mode 100755 index aa810c0..0000000 --- a/.infra/files/scripts/seed.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -readonly TARGET_DB=${1:?"Merci de préciser le nom de la base de donnée cible"} -shift -readonly SEED_ARCHIVE=$(mktemp seed_archive.XXXXXXXXXX) -readonly PASSPHRASE=$(mktemp passphrase.XXXXXXXXXX) - -delete_cleartext() { - rm -f "$SEED_ARCHIVE" "$PASSPHRASE" -} - -trap delete_cleartext EXIT - -echo "{{ vault.SEED_GPG_PASSPHRASE }}" > "$PASSPHRASE" - -chmod 600 "$PASSPHRASE" - -rm -r "$SEED_ARCHIVE" -gpg -d --batch --passphrase-file "$PASSPHRASE" -o "$SEED_ARCHIVE" "/opt/app/configs/mongodb/seed.gpg" -chmod 600 "$SEED_ARCHIVE" -cat "$SEED_ARCHIVE" | docker compose -f "/opt/app/docker-compose.preview-system.yml" exec -iT mongodb mongorestore --archive --nsFrom="{{database_name}}.*" --nsTo="$TARGET_DB.*" --drop --gzip "mongodb://__system:{{vault.MONGODB_KEYFILE}}@localhost:27017/?authSource=local&directConnection=true" diff --git a/.infra/files/scripts/trigger-indexes-creation.sh b/.infra/files/scripts/trigger-indexes-creation.sh deleted file mode 100755 index a9df613..0000000 --- a/.infra/files/scripts/trigger-indexes-creation.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -#Needs to be run as sudo - -readonly LOG_DIR="/var/log/data-jobs" - -if [ ! -d "$LOG_DIR" ]; then - sudo mkdir -p "$LOG_DIR" - sudo chown $(whoami):$(whoami) "$LOG_DIR" -fi - -trigger_indexes_creation(){ - echo "Création des index mongoDb ..." - /opt/app/tools/docker-compose.sh run --rm --no-deps server yarn cli indexes:recreate --queued -} - -trigger_indexes_creation diff --git a/.infra/local/mongo_keyfile b/.infra/local/mongo_keyfile deleted file mode 100644 index f3097ab..0000000 --- a/.infra/local/mongo_keyfile +++ /dev/null @@ -1 +0,0 @@ -password diff --git a/.infra/local/mongod.conf b/.infra/local/mongod.conf deleted file mode 100644 index 9e63387..0000000 --- a/.infra/local/mongod.conf +++ /dev/null @@ -1,8 +0,0 @@ -net: - bindIpAll: true - -replication: - replSetName: replica - -security: - keyFile: /tmp/mongo_keyfile diff --git a/.infra/vault/vault.yml b/.infra/vault/vault.yml index 38394a8..819e3e7 100644 --- a/.infra/vault/vault.yml +++ b/.infra/vault/vault.yml @@ -1,342 +1,69 @@ $ANSIBLE_VAULT;1.1;AES256 -64306433376534323237306331326339373737303939643138646434346433353265383731386334 -6463636364663863373734313233393065323637666165650a613232303565386535353830663466 -33656231356664663639383565653433623365346134343965323437316635303938363730623439 -6239306632363233610a303730666262643864363162323738333364373230633534303036613463 -33623261303863316237336639626436373032623665613034306630343665356366313866633031 -66396663303032396234613531616338336439356233356664666532303933633262653830396434 -30373761333363363530356630303137613766396235356235373132613865323766616664343939 -38323835356330636236313063613065363833363931616261656534343465343535323264333438 -32616361326139633232386664386161646130343635353938356638613234383263393565643739 -39646234613830313234373338333236613433656238336139376466626262336333303761336531 -66376566636330616439343862646431616338613535393837343234646535306561353665623331 -32326363623437633132636461613935373061663266383638326439333964623930383930333663 -66633732366539313565363636333339333131346234346263346539613236646162386131663336 -32303931643239303335366134376130356234376164346232656361666264633832653932613862 -61616661653062623331373639306332653736366436643838386565376232633237343933316363 -30343234383363383035323132303132366231346566643836386538353966636266633633633034 -31306163663039323963393433393863653531656438303130333430303136653866336637646239 -66326661353864353434616536363337353938353933306561356331373565303961373337393637 -37663265663833653138356438303435373735373633643634383463366337613837303730343862 -64386536333564366633346463326638383336303934613533323063666463623163636432643131 -61663237353737653530386539333138373463656238666234646136373433666261326339303839 -32316436623536363830623933336132393930303436616664386135386634343536646130653962 -34353062613332373037396137356562393538616364346133363730353139346238666333623564 -64666261393763613935626364383264376465313033303435656466353639303561386234333737 -32376137306538636438663035666664343034646464643965373432363133336633626431363234 -30383039363134633035373264393338386265303762306661343665313232383033363163313161 -62643362386630623363366265333836363833646630653330313939666630623237303663386362 -66393338383637343564376439613362643633343866333466643934376564343862343636333463 -61643265323362356332383630366333306134303136393737313962376363333236613664663139 -38373535626332636431316439643064333766643938613339306632393837346234666134393062 -37396537363866643038346130363533326437376235303061656539333633366137356333363435 -30656630323238616563303130353266623261306530393235316261306632656238333566313332 -32623433626238373131663836376464646165343635333466396330333064393737396430363136 -36356432383538303037616132303030363637393338363734356335613137383632343937323833 -32323965333033626436383433313561633634356632656639393862363834386463646137373461 -66353236313539626565313264636563663562323732636164386561323363316439376231643930 -62333735346339666363346166316334616236353938383134623839306433666466306135643764 -34656239643035383736623235363161616632616636313966643939623831613162636231366264 -38353766646234613834313566326462353432376363646361313030643863626338396637353037 -37383436376233363537666332363739343130616265366630616562613335623965656461356339 -61313161313135303865386363346232636261346639643339303264346461386262653032336530 -62393137376139343530373763643061333966323661666430383735653561643839323635643536 -37393066636539666263636430373839626135313832626537646431393538356563656433353331 -63616539663239346338343836376461363665303164363836376435353661383239616665373536 -65376534323237613662646164386637326564323038396330333764303636623336653666363738 -36663237623761383564653761376632616461303563623830326630643664333032623763323136 -35336135303830643364646236616232313732353430343534633732653865666335643536393035 -39356138303161303966666336316131343861393162303961646264616231336135343533383032 -30636265313766393535373637373234636463623636636161353261666334336662303339363764 -33623238623633663434303638386230333539653138663337613739323232653739356636643265 -62353063616533393663323831663566626334646337303930376266356239613732393537653930 -63306436633562376537653065323762393532336263633836303632323063636463343136653636 -38333530373261386334386237646264323835316134633536623063633137363030396433386164 -36303531656165636465623631616134333534366137626531306135626534396330633537613464 -30613738346430653639383237353866623364626133326137316439646164663039383930376235 -66366637386239316132666535393965656164663066356230653762623234323730333632663365 -35393537396633643932623433353430393065336236333166316232376638656436396332316438 -34306366623535343862303234653137616138646539393135626462393939633035663433656462 -33356136363534323931346161666163373031613933616536653237646635633861646164346638 -35356565373436373166663431333135613563646531613765616534613035353761626239656133 -34366563346532373136353136313434636138343336613466396166333738326131366236653239 -62653563653434613139613663346436386231623230653937353838333936626566613432383536 -34616532633863346662343339346139303765383539353462643537383636636465313839383339 -63353132613232633065653332373535656564343163373432396465643631383532363461613036 -39346561643430303266613535316533353130353432626365393231653932633236333932666564 -30393939303037623733383866353339393263353837333236303437653064616261623764623935 -37633362353065363830353736396433303764633539306434316563626366346263623866626266 -37393437343163653132333935303936623230626537356235653931323537333035323038313938 -63336663383239303637623861303661643263633862663339303163333263373162336465623936 -62363866333530353138343666376639376236336262373339613661376265346564333435326365 -31323466333936353333633939373065653334653233663762393739643930353739666334343438 -35343162616335633166613234643838656535663864633233363064396363373662333839343163 -66663065333338313461646634356662613732303561356463386237343365363733326662303139 -34363661386136623130366539363965396161613433383332336237383236333131636635663739 -32363332336161336666643935646432646631663735303732386133323732626261393535623934 -39383964666166333431626136313432316265616139306261366635616338363162613937643838 -61366461623263636365383562663531356637636134323331386632383830356166366263383036 -61643738343637383935313966653463623666376461613037643832316263653036323938323030 -36383135383035323434643635353930343437613162326339656431386665656462313035353234 -33373036303635643262333066343739663135366563383461383464363763316132666636363862 -32663864376438383561623132656263333237326431656439643865396631663665353463303432 -38626464656531613862373438313463303162376336646139626666643764326239326238646564 -66346330333234303139643466393434343366396639393933613265393737323339376337613663 -64373630323933383735313630636539383566336232613931303866323535653665666631353135 -34646233303762313731356439393065613435363766353065363136303136623864663434633638 -64306463623034633139326264383734363061636464396164323265626437363865336534326535 -63663364306234613837663235343034653632656531616365376466396139333635386662323530 -34386661313461653530333961313037323536653865653237393735343464333865613434623665 -35656633323732366462373530643338643561653134666135313365333935313862643933313231 -65393431386439383739373565663035373661663634346364376539383639623036616434333235 -61323431316566386663653364663233306537396266373332626339656635616233316566323866 -31666564353965313864613538666564663361663664613362626632666130313964623062663231 -38633335383439653130653432313534663731623563343331363366333463333061303837643033 -65383838356639373936656131613063396336326636353930336261323035386230333236363964 -30646439303132363435643230383634333033306132343634336138393733323961373330316132 -65663932316562336536666238626333613964326332663935303139373338613338646533666261 -64626139356332363031613036623264353339343466373765336661633039633861653731356139 -38613266656566333663643031313336336331613266313566363435333965333664643636396364 -34636463666138366436633365613235383736303736346234623934653730343539333234613433 -63346561626137656232313937316263626661366664323361666239666633383466373934306133 -35313339623262376561376630343632633033333733613532383131613466336366653665316136 -64633665396534626366343533373465373561396462376638663833333330643362343861396566 -36353136316334363935646234353332333232623233646535363932323532613263663861663535 -39363532653832353037643438366465666436386163643062366339343264653238346431393530 -35646535623564663631646538336263373336613765323235366434393266393235663965303933 -64616431383239333836313332353862636433313533373761316338396338303131613466613533 -33353934373266323833313432666562303565313661663338393231373764353564303965643930 -61353462656461663265343663663566376662333038393233353839646235323832653363646138 -63336338363365326233383938393433663633643334643437373862323364386436343433336535 -63653163386466333039633166323736376637303635376437333135376665323439353338373338 -61376335333933653737653364306265373436323032316335623230346362383739353636386239 -65333330376261323661353636626331326236343637306561366336323063303235336132336465 -62643163376666306636633263326461346139303962363365343934356434323536643639643338 -65323362643931663537353338343133386437653433616437663834623631636364636232303336 -32363730383137393663646261663435326331363839326436316536343665346466633130336135 -33386136333136623764643664316530663535383864366232346532623164336164643733313263 -37653264623132383064376263363535613333616261613062303633393266333931306664373066 -30656438363036646131393761386438356536373533633138323838636137653163346436633466 -39376137613563663663363564613533353230343336383831633165333166316663643861383332 -34316430336532636139303234386365396633663938646665333731313230356332393263393463 -61333437373164396633393838653961336466643635353334636432356538353530633462663264 -63356161353630356462313563303537323234323363613236376564633566343733333666323430 -38646639313935386337626233666565363831623461656630336230636230623030616330313635 -32366162396136613062313731383635643461383561343138393238353661623566343730353539 -38643761376363323462383438333537353338363834663431616265383335663432383038306131 -61626638303732643136653538313632376163643433373838626134633062303238303030363866 -39383139646135383864376365313735616635323362386364316231326631393763366633633635 -66383336646436383033363837326139656665326136656166663666333831616439666139643034 -62613165633961666538633234343933393333383264623131636165346264353039643434633639 -64663038633266383064376561313665393234333934373936343363623161363163666463653062 -66326332353030303532656535323265323338626138343437613737663533333233633736356634 -65383262313065643030386165313831636638613665633564363161646137653430626438613461 -39633963663735336135613966323536613363613364306562333364613731336333363865616130 -63313838376134393235373661376566303561363262646538373039303736626163636463663238 -35386636373134636166373163373533643234613533353039306230653163656562343138356538 -63626538353466643664653231643938333263306639633561313537376338653437333761656635 -30613033363737646665613862663963343563663765313632633633383335336665653761353938 -66613666663239303434653238376439623136333036396130386462343138366361336362356434 -34366461656363306364623430396263333339353761373730636335353766373434653532356432 -64633263316263653239663736373364326638613061306635616233386436623964333363383235 -39386265656566653562623033343138393062343361363639356337613036633231396438363865 -37353837646233393964666433393533313863343662346430353033396561316631633361653533 -38303832373939346539373437326362353639333332313061376138623531623232346339383838 -33396165393834393930653465346564373139633965313762633564326538386634376631613161 -61643661323533313833663836336432653661383333363737613138386238383764333938396161 -61356563383565383634353063346264663661323337316536386336336138396539653061663337 -38363238666366376335353235616338623032326531613665316630303564663362366631313034 -64323961346365623133666363663432663465656435393164363332616538373666376537333532 -34616266613230613432313964306536653534343037653036316530353263343266383663346437 -31326636366438333734333361656166336261323530643138313961653433386136336563376563 -64663636656436376635343566343035653335646438356332626236613134636231363031643135 -65313663656664656534393631303165646465383065656362633864613661343166643565306531 -33613532356531336534396230333738376139626230653038363338363532306535373636303262 -62336339663633333834633664323265363837616131616537353861316534346234613038633038 -62623264653864356665656437313861303761323963393666333539313761373562373239376438 -66653263313130373333386362346166333863373036666463633339653165353536653165326138 -64636262333630646130383936373464346363366566343166646265306431343034613466663964 -39616137613834633834656664386363323939373139323030623633356634363732396665323766 -31643330333232636630376162623532616330326437326435313132656235313036316431643165 -66643761383530663933353334396530643332346461303261303765343039636532346636396430 -32666638376564353338643935636464373665306639373931623736373238663030613932623137 -64663837376436323330366337383732333266313732653836626135616137356566316463373535 -64323835336530313130343837383239636230313066303830373035313230306437613837333039 -37623663303936616235636539326630363333616335303135333935613035626466396438363335 -63383665336539356564353036333664393735623734336365633634623639666335316432336666 -31323166666332643063323562356461373239656366376438396231393462323561383237383235 -31316637383330393364376530343064356537333830313564663833356239333263663061346266 -64613133613830396563636463313830333031363833356534343864613661393465353363663163 -36613832353135313163663839643466643333656535663330326138393338333464363738376535 -66626136643433313630636266393664666266356562323436643063313735313465353962646661 -32323666363439393161356266646264613739323565623038386131356462333665373532343932 -63336535306464346135626661383165373934376364383434323966313130663030633331646162 -63393763646539666430616565636539393466383662346330326164393664363761663166353538 -61663763623464356632616561363836616432343764636565623131393963353665633464343266 -30386536626466326337333039323132316466616439646564323062386230656466623736663061 -38336539313364616236326562363038383936323764353830303533396136363764613962343364 -36343835383564336131386531353466633661316632376539383032313166643335393337303831 -36613533356435663636366466393132333463326231383064663038383364623761353763653239 -64326161383061656230323263313330393639306665373132643634336234626133623132653532 -64623938396237393631373163623839353235633566316236656563323936396632326238613535 -65346364306133313836393563666631633537633132633933333432343038386637643466613330 -37376265353864623338333137373534343162626663343063326235316435353430616262643136 -30356232623664323066633764396134353930363239353930646438663933626563356338633663 -30643736343630313936393762393366333262666137633232376133643062386362396234623133 -31623139393164646630656635383239323434363361306138383163353731663831306438333963 -64643863313664346239646162363066356561343563376630626632356337356461333362633633 -36646634613039626666303239333461653762373966383966383033663435613363323837313130 -35626539326238623265366262383134333963323434613639396231396531333538613230643764 -66653063313764373762343033343434356562643736393637633532396165333337653030306538 -38323437343530393938306536343039333630393030623036346233663839323134353061316365 -64653739643066363335633065633637343436613265623334633632363865323237356337666162 -35316230663330393032386430306235643765346633626664666166666365376462666338313039 -38386430663066633866363139393163373631633833626539653033303731653130636163326562 -64313236356463393163393834356365353431373730353564313463383239383966303131386133 -35333261376330376130613038373636383563373861353065613366653266336534343630353164 -39623434366534323837646634653239373364663036373834626634356132343635396136336564 -65363066323736646666623734343462346631343563613330663630343137393266336336623036 -33613362376462623362396137333031363565313862323465353630656162313132643066646163 -33376335343334653464396239356239346532356266396334303062343637656136633638383530 -62396637336439613033373633323763313764663232343833363631303031353234303861313566 -35393462653466623935346237373138393331626632356661366531356230333334306538663038 -61333866643735306564653165326437323862376235323061373032396166643937383265653063 -64343863393332336632643563643463336339643439383335616436386132363534313062376366 -34626135636266336531393233616263623936633861363737306366666365313937666133306237 -39613532356635643332663162666238653239643432376230353539643532663730626331636461 -66653338366562633663366134363130393730363037346432376337376639366263636237643937 -32633962623565623463373365666136633666313536373364386263386231623562656164373965 -38353538616337386430336139303566363739656538663731376430393638656564316363326639 -37343365336561363132626566663935356538656530363663333635366231303832383931656464 -38373731346137616364393933323638313262633138623063656134363630613166363661383164 -62396663646366363264663132316561616235656133376431346163346334366436333038333163 -32643031303364663133643264313731616231396662356539646662353333306532616333353462 -32383930373965616639653465663034393438383030313735616632653433333538333964313734 -34323836343762343732343834313266343566633935383239653035363064656133336535323039 -37303138663337386637393334333138376362663266343739636639306434356532336538396135 -63313261346233366334383335653139656239393432323561366462386434376462363465363833 -39316332646562323264666161303564376135643731336637323864656637343534353231386235 -36633365363861396664313837623232393436636333373233366265346136383536653962376633 -39313232366136396334346164333461373739653763343564393335313662386539343661636238 -30656265343363323661616164666339313066383434616430646261656432633030366463363966 -37373035313433333266633037356433336162633831383366373432373735346565623635373563 -62306361386137363965656433643538326337633437303935343930313763383438356239643566 -64623739316533333933346365313535366262636665316264613763646463346432323133376465 -35306263393733393639393231343864326431643863353437643930653039663230366136313833 -30316331326266383935333662326631336239343636663763626537303461633461376163313935 -33383839613533333936323336333361366362653863393964633035356531333038653236326565 -36353266626637333061386666373166333234623966383265383565663833613033626331616335 -62366662386261646531616236306166656166393730616133336564333133313161623236613563 -37616137343431303839313965373161383435383430616331623034656639323262386466383365 -32643763323362376435383939663137623537373837326531383134346234386662343231376338 -62373964306665656462636137316664343231383963386130366632323037373463333135363732 -61636466353733326336656166643163626261373630316338646162663734353961373235663165 -35626131646237306132666632396538666339333532303165393138323064633864376233353331 -37353766306666393663636632366432313064643538343634633933386230663465383635393337 -65373135313731643936356565663166393062393261333763643866666431333664346536663139 -38653737363261666164626163396361343339353737633631333462633738373262643137326462 -30346536323962616238376164386538383166633931386239633563653263656338326536376538 -36613131633538386137623935653236333632366535653736623439326534643937393733346666 -31323035616339383264323166343265336530336261333637626265616635343066616131333962 -32313634323662306664333064653264646637393064646638333836356364363939376330393066 -36633463343434313635333234663161363937346433393139613132376265623931393566366333 -65306366626261646262383564373030623265333231663230383230333833386466333662363763 -62306135343830356662666230303163633064666538363737623139356435363935356165643861 -37376232336336636334663065623262386433303031353631386432316662356133333335326330 -66663131376136326262636533383433343934646566323532366563616332363733646365613635 -64306338326461313232316639656262376466383663333765316238326363333066386231333265 -36643837643439663961363330633437343533636437666334313533656661636132616161646263 -38376365623832353134636132343834656463306463376562613632303032636264383965306361 -63346537636237336134383966313733653237383761626162343737303935363061316661326639 -39363631313939663364636532376266616362306264373266333135313365666139303738393930 -65393939646334323666366366366539613938366666643332653266366365373138313038343063 -61636531303165656665613463393237663135313763663364656462333533613730663961656330 -64326361653134316439336530393635616661373031353737316564366266343462336563613563 -66333431366331383566343339616566393435363561343339643635313137346637386434656135 -35346362373566383538363435326531393331353866316164613336363563623065363631316339 -65623835386630393134303363613635613530373264303165313065613630336133316235613661 -61656330373530356330376366343661386337653439623132326664663830356537346262643538 -33316434323434353134353939396437336232373765303237633330663433313362383762363533 -33336332396537663732643062336264303661653037643438373466313539643630646638623331 -36323637386138656436336135623265393966626634633061306636333739393065656165383234 -37633865343638613566613437623231306430336562373832616335393562346638353630386164 -36376265623364326239316232633234316434353865623630663262376665626136623762643664 -36376238346330666566303334383036616632336361326666656135633964326366373262346635 -61366231393639663066616262643332646662616336666632373031393462646561626630656536 -37636531346362656339363638393639636162383862316534653566643231383431643530393963 -65363364373530636638613938313935323061646266303634643139636564616536393636663536 -38393032653631333363336562663465386363393461313530353664373531393437336364393538 -31396163626233303039373039386563336365386436313631373734376239313765373866393362 -30613461623866303030643130333361393566376361376438633531646135343862643137306335 -33343130353138366635616261333532366637386333346235633233386338336134393864623963 -37653138623331363539656663383430613631376531316430376161313331356434306133626265 -61363630623566663938363264633837643436333734643636366263616263303139343666383936 -32373066383732316535366335666363303533616365343031316335653766383164323934376536 -39323535623638616264346537636332623631343666623539363262393131653636353062336134 -65643563393435666332376333663363643335663661393561336564356630363231653335396364 -66343661326637333165346163626136333739653466333837366433396666373061356234323862 -61343137653863393835653436623566613635323864373433666339656530336362333364373537 -39623166363930373834373537353237653339303862393634346432316365373362636237633130 -38323532306234663237616537623166326164343035646533303731633731633536643736373030 -61396431616438396530656331323966616430366237383564313039613039323832623161306231 -30363264386438353133653764643038663739346137633336356263663162303361356564646339 -62326166613938303031336466383635636634613538336331316165663633653665333339313532 -38363533653737366338303465393737653364383432333436356161653933313835383339653134 -65376364663831393166353035343665653539626636643066656336343761336264636662666562 -32656230376163336536633436626131303866303037646435623163656534643862333036393862 -39313965333930343232386434303962623830396432373130393834333434633136333437316336 -33343465343239653763653965323463356261316237313636613839633765636434616331633939 -63656361393833306237623439653533356437363436376137323533373433663535643561613361 -30633362383366613261373063633538343162343866383962636339333238616436646639613434 -30353932306565376234373966666538653166633833633638616139623632656566373631346162 -62633764313832653739663034393663326536313666666232353735306133323536666637376361 -64326137663733646533633735653364613538353830313334356437636463666663636338386334 -62656661366138623566323964336638363464323366323339343634363437333864396362336331 -63323838393762303631343665356662373330666634393534333239386262393632616631363365 -37306361373761326365336630386538643132636563383134636437616333393033633336663866 -38646663633663623761306466323538653865353230363130396561356335363465386533326264 -61383233303864303063613932346333333462613266626230316564303436323331393030323035 -35666234663432373833656234626134656166396230316533343036333131323639333564383635 -34363062646636636433323434343061346232396536363165623236393661633638643538653430 -65376464376433323638663839343832623462633030313931663064313666653231303337303236 -38346534363330313635303366636335663538363562353431353336666230383166366632333336 -61346439653330363330636638313561643263343136393561323138336165623961666331306663 -63623430313434373861636636363364656562306663373064616239316163386261656666383332 -66356563316636636539373966616437346266313835376434313963393863666433666135306132 -39616139623736393236393565616566333239646363316234646565646331323032373963313039 -66613962353037373637633434383033353138353938373235643639313633313061343735383464 -37353032636564626138663539313837356333656431623162646235323934343734326633343739 -61363535386435363862373566643236346532313466303965316639383734656266336562656538 -66323830356238323830663031353032303366663430343436393832636633303133616562396261 -63303634633232396132656561366634386261636437366264363831353465306637646163366137 -66656333613137666330336234396162303334303439346466643365633635396463643563306233 -36373633396232313633366335306165363431643531636133316439623436363132336538653965 -31623961323337303539633932376331326530356263386232666536306433353864613135646331 -38396466623564353132336233636437613865656337623135373038376331343531323238363065 -35636133353663643737393338303266646264653438303135636433343031646364313864343735 -38313766353835323036303062336662663239633931363933346664663264343833633465356237 -30623233353734316664386261393563396661373539303064353134636630656166303138626137 -34666238346339663639363762366662626432396163373838646335663831316132326337383139 -33316262346534613432333065323466376635383834663536343336383835613934373931336538 -33333063306661336534343832336238353333343461313863303432396133663230353633376463 -34366462623164373439643839346636323664653131313237636664396537656637346363393134 -30653965386534356333343032326464633034616663373130356333386161303738373963626565 -32336536343563303430633733646130653063396534376339316634383431626333396130386534 -37306366343934383938313436313532623033323866373334386562636363633934316235633237 -36333739633936616163616234643363376234613639623064326461303362343137363730396339 -31363037646664396634383430643132376131333866313233326633336666303332346438336465 -64636336613062636433343866613337323137616466343165393734666336323265613064613461 -31363132316438373536396333323964666666353236373331376232323964646662393064383138 -33366564613735323864626338396133626334353937346565323861656166303663656364643363 -66313533323261386166386631656136313730393234383932376232383330303139393037313435 -38613536303235376334656231373532396337303366396664303262623336306465306636656334 -38613239306661613861346639343631366664343031303833333865323834313938343666366433 -63383233343535303963333337303865306335666561356437366637393534373731626235323730 -35613039303363656231363032323937326361393130616232333034363464303362373530333665 -38316465303135616639633562373334306137636433633634626362336665623763626330393539 -30383735626361323732323532663134653765653230663838353937613035376331353937393735 -39303264393035383862643166613336376566336438303739363065366464643731363162353666 -63363134343464616531383135643933663237303339636339663638613034326431613131623933 -63383537633561373332643533646633323236363037303637613264656365653939366134613431 -64366363313436386631313833356637643730316666653262363836373436316366633939323231 -33316638363436616639336561353034613165633963383434656339633861356262 +66376237633765306462363165646365633661666232663330393332636665393234326362346166 +3964653736313462326334363365356230353633346530370a663435616237613961636564656166 +31383165343234353462313237393431393263353962613963623233636238653031386562333632 +3162363839636133300a633032323838383238363531666435636338653338626138363339343364 +33623766356634643164383330633266643465633037393663346137323563336265616333613262 +39306236656434616432376633633435386265653134373162663037323535643565313734376266 +61383865376164666632393062623933373232383063626534396165626633346230383161613364 +66313834613565316364373935393135353666633861343031663262666438653838333466336464 +31343830393630313737613838336161383466376631343736316631616261616562663836333937 +31306131663730633433636538653932343462623931356366323561316433326435643865383332 +35613032656634363434343032353463383138383764326633656331343438666535323561633834 +31336537663136366231353236633736393437666561666532376132393665666561633532343263 +39336439646231663635383264306336633763373834326331353030393361626664616138383837 +61383963326664363237356138366431633565663138663833663234346364613639353861366538 +36636263373365313538386664356365643866326663386562653138366563313765333566343965 +32376538623139303738313162636561303465643531323335353739616366653464386161653965 +35323430623739663762323933326439313963623661333262303737356638343934383935383562 +38363031343966636566356162383630316439386237383237313531643263373164613637316133 +33306134393335356464303934383231303866656165373164356630306530346231636564333537 +37646236646331643833396133333930323464383566636532376337633564643263626438343563 +36316535333064393361303232613961643831643865363965653736386338313962336166636263 +30643931386432313337613031373063623265633631613436386531396261643337313663383235 +64323230643464303866326266323839316337363138663830326431633565316165636466366431 +64336238343738396432336431613363643065616565396237616366363262376135386633363361 +34376165633866313137303661336332643830366636356139663336386231613538633238663335 +31353634626435396339393664333238343964666562633232313133313366303035646135626635 +33663234316431333265323462356366666538373732386539333031366139313937363462633939 +36653462376265323631653438383665356363633636346166393133626530343865333336656365 +66346265663235343036663966393264373961616565633231303864366132333330393265623064 +66653635643536356330363132373230336530386566323531373139613935663032363834373635 +66346362343261323437646266633333363435663734366133323338636563363130623331323437 +65643130396565316433663431666666336338363566626432653138656139393531366565353536 +35323162623731633563623532366430636138646437653166656238616461396539373165653136 +32363661356261333238373666323139633539393135363135383464346337343039383533663339 +62343931303563623531363339353432663964323935646139643338316365653062613461376139 +30353461643133316531376538383030656464383836323862363433303039656266656462623063 +34656331646238383534336136333837316665373266636465636531646130363065393061393337 +37383661653261386664363164646436656137346432366535363439626531393064336632623163 +32323265303438616565366562396536626432653939643165386635326464333030336166363230 +66353264386531306563343164346561656562633764333531393833633861653766383737653837 +30316337623364633066646331613433663237626436303930376432303761353130663136316663 +32393237313365366136663634623433303737383232386666316163636433323430306639613832 +33333731373437393562326166636563366561366666343235343433623534653761666566633063 +35613735346535363432396166373537633466336330666538383833383039633766336663656332 +65393433356434316461316164346234636435653561303937666565636166373564616565326332 +31393666306132353963326663623432313363306531643964376435333464356466623962613666 +63303634653163356433363865353064366630626230626138313637386233646436643637323436 +63643537333436343738643332336537666461383436643735316463393831633132663631656130 +64363437616631303335656238613833323934383634386461373331356633656435323830623638 +62636630393436303734393933636638653539383934346663613230353561616131323536623330 +64633033333736323665313963303933643561376437623831366561626163653333376537333230 +36633033363639653063353533623664623735623235666165363235383163386131306665663163 +63313132333433663966306339363030356664623031373330353935636162303262663963336538 +36363232326665313235326233326236326237353962346635623964353533323135356138393134 +37363461363162663531303738623563666562326363666634316166656433306531303961323931 +39663135306162303661373537626262626563373031373035643166643037356166333661386636 +62383639613463323437643339636533336561343138386263656164396164326665363161333836 +65316430336438613964313533666530333131323165353266613934366237383733623834383934 +39613030633164623230386130323334653433643965326630363866666365643538613564633734 +39643465363566373935656332323963336336336563376261363439396237646132356230343261 +34643864366331626163313361353865626163346363653935633931646363356434636566393039 +63373032666538346431666236333366396538363264613261323765373530656130633239383934 +66363530656338333761623633646131346233333663366364366435386530306438333563633030 +37393862386261353632613332323637663339666331313237393638663962326161326635616364 +66376561343532333630653732393265633436363230323061323965643135613235323361346666 +38383366373162613964626535343637656438663033643734613036303138346566363662656664 +66636162633439383466663335363365343232353631646231663830383939356366643932356632 +31303764316331316239 diff --git a/.prettierignore b/.prettierignore index 5cf230d..56e021d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,4 @@ .yarn .talismanrc -.infra/files/configs/mongodb/seed.gpg .infra/.env_server -.infra/local/mongo_keyfile + diff --git a/.talismanrc b/.talismanrc index cb1fe22..0ab9cd3 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,6 +1,6 @@ fileignoreconfig: -- filename: server/src/index.ts - checksum: 5f0d3655a9d44f3436f0dcb4c9f256d8b973cf0ac29867b084ca92e0b9c69ac5 +- filename: .bin/scripts/get-vault-password-client.sh + checksum: 0bb3d08effd4cc3408d2431c02918ee0b63ffff623eb6ae8de7e5f30982f51bf - filename: .bin/scripts/setup-local-env.sh checksum: c9d412b132f3a7b8b6bde35f5acac94d1fffb87ce5ac718b6abc54b214899be2 - filename: .github/workflows/deploy_preview.yml @@ -11,14 +11,8 @@ fileignoreconfig: checksum: 6e16ba596ed40c0c03d896216887d76f594f352158c61c1246e630c70cb87552 - filename: .infra/env.ini checksum: 3b78c6c25fa45ef557ba7e10d27cb58233bfbbf995c0346477ddfaf980165972 -- filename: .infra/files/configs/mailpit/auth - checksum: 23b23d13d722d209d16c8c3f91cecf56eaff968d1894f7c72f1af33ff3006c69 -- filename: .infra/files/configs/mongodb/seed.gpg - checksum: 1b1e81c2812b59898649bd6c46d3299275f9593703847e58590d46ec7eb405cc -- filename: .infra/files/scripts/seed.sh - checksum: a673a8f706cb90f2f5c9f98981b06ce95c566e67e2bb4a6323d6b1bdb8ef0233 - filename: .infra/vault/vault.yml - checksum: 8df9d93924be40bf6855b14b1518c9185009f6951b980efe29e1354d79771a53 + checksum: 3432408382852d4d3945716a285fd7a060d9d2e890a2c87e2d96b6456cba2639 - filename: README.md checksum: 00ac991f0b2746c5a5ffa14e2b3c5427b739c0d952aa3730efe1f234ac1fc3ca - filename: docs/developpement/1password.md @@ -27,6 +21,8 @@ fileignoreconfig: checksum: 137f146297aedce399926c6ddebe9bbfb22b0e924bbdbd30be2b4654f6b248ad - filename: server/.env.test checksum: 5db82cebee68a3b56ada7e564679b9f53541dbc35a3ffdcf59fcbc9b6d41a0cf +- filename: server/src/index.ts + checksum: 5f0d3655a9d44f3436f0dcb4c9f256d8b973cf0ac29867b084ca92e0b9c69ac5 - filename: server/tests/utils/security/accessTokenService.test.ts checksum: 017acd9d128165e6edcfd2c33a0f218c53b0ba2b4a77f3da3fe7b58f11d6fa90 - filename: server/tests/utils/security/authorisationService.test.ts diff --git a/.vscode/terminals.json b/.vscode/terminals.json index 86311cb..06a9d24 100644 --- a/.vscode/terminals.json +++ b/.vscode/terminals.json @@ -5,7 +5,7 @@ "name": "Server", "focus": true, "description": "This run the server", - "commands": ["yarn services:start", "yarn server:dev"] + "commands": ["yarn server:dev"] }, { "name": "Ui", diff --git a/PROJECT_README.md b/PROJECT_README.md deleted file mode 100644 index 0c052d1..0000000 --- a/PROJECT_README.md +++ /dev/null @@ -1,15 +0,0 @@ -![](https://avatars1.githubusercontent.com/u/63645182?s=200&v=4) - -# Template Mission Apprentissage - -## Fiche Produit - -**TODO** - -## Documentation - -- [Développement](./docs/developpement/developpement.md) -- [Déploiement](./docs/deploy.md) -- [Vault](./docs/Vault.md) -- [Infrastructure](./docs/infrastructure.md) -- [Sécurité](./docs/securite.md) diff --git a/README.md b/README.md index a2e70bf..0c052d1 100644 --- a/README.md +++ b/README.md @@ -1,264 +1,15 @@ ![](https://avatars1.githubusercontent.com/u/63645182?s=200&v=4) -# Mission Apprentissage Template Repository +# Template Mission Apprentissage -- [Mission Apprentissage Template Repository](#mission-apprentissage-template-repository) - - [Pré-requis](#pré-requis) - - [Démarrage](#démarrage) - - [Création du projet](#création-du-projet) - - [Sentry](#sentry) - - [MongoDB](#mongodb) - - [Postgres](#postgres) - - [Env Ini](#env-ini) - - [Mna Binary config](#mna-binary-config) - - [Secrets](#secrets) - - [UI Config](#ui-config) - - [Other Files](#other-files) - - [Mailpit](#mailpit) - - [Legal](#legal) - - [Remplacement du README.md](#remplacement-du-readmemd) - - [Seed](#seed) - - [Github Actions](#github-actions) - - [Organisation Secrets](#organisation-secrets) - - [Mettre à jour les snapshots](#mettre-à-jour-les-snapshots) - - [Infrastructure](#infrastructure) - - [Initial Version](#initial-version) - - [Monitoring](#monitoring) - - [GitGuardian](#gitguardian) - - [Github Settings](#github-settings) - - [Shodan](#shodan) +## Fiche Produit -## Pré-requis +**TODO** -[Suivre la documentation dédiée](./docs/developpement/pre-requesites.md) +## Documentation -## Démarrage - -[Créez un nouveau repository en utilisant ce template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) - -Clonez le nouveau repository locallement. - -Récupérez manuellement les fichiers de git-lfs depuis le template - -```bash -git lfs fetch https://github.com/mission-apprentissage/template-apprentissage.git -git lfs pull -``` - -Récupérez le vault depuis 1password (assurez vous d'etre connecter via `op account get`) - -```bash -.bin/mna vault:init -``` - -Vérifiez que vous pouvez déchiffrer le vault via `gpg --list-packets .infra/vault/.vault-password.gpg` - -> Si vous n'etes pas autorisé à déchiffrer le vault, il faudra se rapprocher des personnes habilitées afin d'avoir vos accès ajoutés. - -Initialisation de l'envrionnement `yarn setup` - -Vous pouvez lancer le projet locallement via `yarn dev` - -Le setup va intialiser la base de donnée, il faut maintenant mettre à jour. - -Vous pouvez maintenant lancer l'application locallement en [suivant la documentation dédiée](./docs/developpement/developpement.md). - -- TODO: GitGuardian, Shodan, Slack Webhook, Uptime - -## Création du projet - -**Pour une simplification de la procedure, nous allons supposer que vous souhaitez créer le produit nommé `api`** - -### Sentry - -Il faut créer 1 projet pour l'UI et un pour le Server sur https://sentry.apprentissage.beta.gouv.fr/organizations/sentry/projects/new/ - -### MongoDB - -Créer 2 instances de MongoDB sur OVH pour recette & production. - -Pour chaque instance créer 2 utilisateurs: - -- `app` avec le role `dbOwner` sur `api` -- `metabase` avec le role `read` sur `api` - -Ajouter l'IP de votre server dans les IPs autorisées - -### Postgres - -Créer 2 instances de Postgres sur OVH pour recette et production. - -Ajouter l'IP de votre server dans les IPs autorisées - -### Env Ini - -Mettre à jour le fichier `.infra/env.ini` - -- `product_name`: le nom du produit `api` -- `repo_name`: le nom du repository `api-apprentissage` -- `database_name`: le nom de la BDD `api` -- `domain_name`: le nom du domaine `api` - -### Mna Binary config - -Mettre à jour le fichier `.bin/product-meta.sh` avec les memes valeurs que le fichier `.infra/env.ini` - -Mettre à jour le fichier `.bin/zsh-completion`, remplacer `mna-tmpl` par `mna-api` - -### Secrets - -Mise à jour du vault `yarn vault:edit` - -Mettre à jour les secrets suivants: - -- `SERVER_SENTRY_DSN`: le DSN du sentry serveur -- `EMAIL`: addresse email utilisée pour envoyer des emails (créer un alias sur https://admin.alwaysdata.com/mailbox/). Utiliser une addresse de type `nepasrepondre-api@apprentissage.beta.gouv.fr` -- `METABASE_EMAIL_FROM_ADDRESS`: Utiliser la meme que `EMAIL` -- `METABASE_EMAIL_FROM_NAME`: Mettre à jour -- `SEED_GPG_PASSPHRASE`: Générer un nouveau secret `pwgen -s 120 1` -- `MONGODB_KEYFILE`: Générer un nouveau secret `pwgen -s 120 1` - -Pour chaque environnement: - -- `PUBLIC_URL`: Le nom de domaine public. Pour la preview utiliser le format prédéfini -- `MONGODB_URI`: L'url de connexion de l'utilisateur `app`. - - Pour `recette` & `production` bien faire attention à la DB à utiliser dans la connection string et d'avoir `authSource=admin` - - Pour `preview` remplacer simplement la string `TODO_REPLACE_BY_MONGOKEYFILE` par la valeur `MONGODB_KEYFILE` -- `MONGODB_METABASE_URI`: L'url de connexion de l'utilisateur `metabase`. Pour `preview` laisser vide car il n'y a pas de preview -- `AUTH_USER_JWT_SECRET`: Générer un nouveau secret `pwgen -s 120 1` -- `AUTH_PASSWORD_JWT_SECRET`: Générer un nouveau secret `pwgen -s 120 1` -- `SESSION_SECRET`: Générer un nouveau secret `pwgen -s 120 1` -- `SMTP_WEBHOOK_KEY`: Générer un nouveau secret `pwgen -s 64 1` -- `METABASE_ADMIN_EMAIL`: L'addresse email du compte admin. Pour `preview` laisser vide car il n'y a pas de preview -- `METABASE_ADMIN_PASS`: Générer un nouveau secret `pwgen -s -y 64 1`. Pour `preview` laisser vide car il n'y a pas de preview -- `METABASE_DB_URI`: L'url de connexion à la Postgres.. Pour `preview` laisser vide car il n'y a pas de preview -- `METABASE_ENCRYPTION_SECRET_KEY`: Générer un nouveau secret `pwgen -s 120 1`. Pour `preview` laisser vide car il n'y a pas de preview - -Pour recette & preview uniquement: - -- `SMTP_USER`: `user` -- `SMTP_AUTH_PASS`: Générer un nouveau secret `pwgen -s 120 1`, utilisez le **MÊME** password pour les deux environnements. - -### UI Config - -Mettre à jour le fichier `ui/config.public.ts` - -- `sentry.dsn`: le DSN du sentry ui -- `host`: Pour chaque environnement mettre le domaine associé - -### Other Files - -- `server/src/config.ts`: La valeur de `cookieName` -- `server/.env.test` -- `server/tests/globalSetup.ts` -- `server/tests/routes/users.route.test.ts` -- `shared/helpers/openapi/generateOpenapi.test.ts` -- `shared/routes/core.routes.ts` -- `ui/.env.test` - -### Mailpit - -Les environnements de recette & preview utilisent Mailpit. Il est nécessaire de créer le fichier d'authentification via la commande: - -```bash -htpasswd -B .infra/files/configs/mailpit/auth user -``` - -Entrez le mot passe correpsondant à `SMTP_AUTH_PASS`. - -### Legal - -Revoir les pages: - -- `/` -- `/accessibilite` -- `/cgu` -- `/donnees-personnelles` -- `/mentions-legales` -- `/politique-confidentialite` - -### Remplacement du README.md - -Remplacer le fichier `README.md` par `PROJECT_README.md` - -### Seed - -Le seed doit etre regénéré avec votre nouvelle passphrase. Pour cela faire `yarn seed:update` - -### Github Actions - -1. Décommenter les github actions `.github/workflows` -2. Changer le nom des images docker dans `.github/workflows/release.yml` (`mna_tmpl_server` & `mna_tmpl_server`) -3. Créer le Github Repository Secret `SLACK_WEBHOOK` (https://api.slack.com/apps/A01JENR8874) - -### Organisation Secrets - -Autorisez votre repository à accéder aux secrets d'organisation depuis https://github.com/organizations/mission-apprentissage/settings/secrets/actions - -- DEPLOY_PASS -- DEPLOY_SSH_PRIVATE_KEY - -### Mettre à jour les snapshots - -`yarn test` - -### Infrastructure - -Demander à l'équipe transverse de provisionner les environnements https://github.com/mission-apprentissage/infra/blob/main/docs/provisionning.md - -> Une fois les environnements provisionnés et les accès défini veuillez mettre à jour le vault via `yarn vault:edit` puis refermer directement. - -Mettez à jour le fichier `.infra/env.ini` avec les IPs des différents serveurs. - -### Initial Version - -Une fois que les modification ci-dessus ont été réalisé, faites votre première PR et mergez la dans main. - -La version `1.0.0` de votre projet sera créé par la Github Action Release. - -### Monitoring - -Ajoutez votre projet dans le monitoring, pour cela vous référez à https://github.com/mission-apprentissage/monitoring/blob/main/README.md - -### GitGuardian - -Ajoutez votre projet sur Gitguardian https://dashboard.gitguardian.com/workspace/220324/settings/workspace/integrations/github - -### Github Settings - -- General: - - Features: `Issues` only - - Always suggest updating pull request branches: `on` - - Allow auto-merge: `on` - - Automatically delete head branches : `on` -- Branches: - - `main` branch protection - - Require a pull request before merging: - - Require approvals: `on` - - Require status checks to pass before merging - - `tests / Tests` - - Require merge queue: - - Merge method: `Squash & merge` -- Code security and analysis - - Private vulnerability reporting: `on` - - Dependency graph: `on` - - Dependabot: - - Dependabot alerts: `on` - - Dependabot security updates: `on` - - Grouped security updates: `on` - - Code scanning: - - CodeQL analysis: Setup Default - - Secret scanning: `on` - - Push protection: `on` - -### Shodan - -Créez un compte [Shodan](https://shodan.io) en tant que `Member`. - -Ajoutez la config Slack Webhook pour recevoir les alertes. - -Ajoutez vos urls à monitorer avec notification Slack: - -- .apprentissage.beta.gouv.fr -- -recette.apprentissage.beta.gouv.fr -- -preview.apprentissage.beta.gouv.fr +- [Développement](./docs/developpement/developpement.md) +- [Déploiement](./docs/deploy.md) +- [Vault](./docs/Vault.md) +- [Infrastructure](./docs/infrastructure.md) +- [Sécurité](./docs/securite.md) diff --git a/docker-bake.json b/docker-bake.json index 2d28503..1f81412 100644 --- a/docker-bake.json +++ b/docker-bake.json @@ -13,9 +13,6 @@ "recette": { "targets": ["server", "ui-recette"] }, - "preview": { - "targets": ["server", "ui-preview"] - }, "local": { "targets": ["server", "ui-local"] } @@ -50,7 +47,7 @@ "ui": { "inherits": ["common"], "matrix": { - "ENV": ["production", "recette", "preview", "local"] + "ENV": ["production", "recette", "local"] }, "name": "ui-${ENV}", "args": { diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index fd1da59..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,39 +0,0 @@ -version: "3.8" - -services: - mongodb: - image: mongo:6.0.2-focal - restart: unless-stopped - hostname: mongodb - ports: - - "127.0.0.1:27017:27017" - command: ["-f", "/etc/mongod.conf"] - volumes: - - contrat_mongodb_data:/data - - ./.infra/local/mongo_keyfile:/tmp/mongo_keyfile - - ./.infra/local/mongod.conf:/etc/mongod.conf - healthcheck: - test: ["CMD", "mongosh", "--eval", '''db.runCommand("ping").ok''', "--quiet"] - interval: 10s - timeout: 5s - retries: 12 - start_period: 10s - - smtp: - image: axllent/mailpit:v1.5.5 - restart: unless-stopped - ports: - - 1025:1025 - - 8025:8025 - environment: - - MP_DATA_FILE=/data/mailpit.db - volumes: - - contrat_smtp_data:/data - -volumes: - contrat_mongodb_data: - driver: local - name: contrat_mongodb_data - contrat_smtp_data: - driver: local - name: contrat_smtp_data diff --git a/docs/Vault.md b/docs/Vault.md index 34c3e11..e3a6103 100644 --- a/docs/Vault.md +++ b/docs/Vault.md @@ -7,7 +7,6 @@ Le vault ansible `./infra/vault/vault.yml` contient les variables d'environnemen - `production` : environnement de production - `recette` : environnement de recette -- `preview` : environnement de prévisualisation - `local` : environnement de développement local ## Vault édition diff --git a/docs/developpement/developpement.md b/docs/developpement/developpement.md index a59a310..a396893 100644 --- a/docs/developpement/developpement.md +++ b/docs/developpement/developpement.md @@ -1,18 +1,27 @@ # Développement - [Développement](#développement) + - [Pré-requis](#pré-requis) + - [Démarrage](#démarrage) + - [Détails des commandes globales](#détails-des-commandes-globales) + - [Initialisation de l'environnment](#initialisation-de-lenvironnment) + - [Lancement de la stack compléte](#lancement-de-la-stack-compléte) + - [Server CLI](#server-cli) + - [Lancement de l'application](#lancement-de-lapplication) + - [Deploiement depuis l'environnement local](#deploiement-depuis-lenvironnement-local) + - [Talisman](#talisman) + - [Vault](#vault) + - [Linter](#linter) + - [Prettier](#prettier) + - [Typescript](#typescript) + - [Release depuis l'environnement local](#release-depuis-lenvironnement-local) + - [Exécution des tests](#exécution-des-tests) + - [Snapshots](#snapshots) + - [Emails](#emails) + - [Debugger sous VSCode](#debugger-sous-vscode) + - [Server Inspect](#server-inspect) - [Organisation des dossiers](#organisation-des-dossiers) - - [Opérations](#opérations) - - [Installation et Mise à jour des dépendences](#installation-et-mise-à-jour-des-dépendences) - - [Linter](#linter) - - [Prettier](#prettier) - - [Typescript](#typescript) - - [Arrêt des services](#arrêt-des-services) - - [Suppression des services](#suppression-des-services) - - [Server CLI](#server-cli) - - [Emails](#emails) - - [Debugger sous VSCode](#debugger-sous-vscode) - - [Server Inspect](#server-inspect) + - [Aller plus loin](#aller-plus-loin) ## Pré-requis @@ -25,18 +34,6 @@ Avant de lancer l'application, assurez-vous d'installer toutes les dépendances ```bash yarn yarn setup -``` - -Cette commande mettra à jour les dépendances du projet. - -Le script vous demandera plusieurs fois la phrase secrète de votre clé GPG pour décrypter les variables d'environnement du vault. - -Il est possible que vous rencontriez un problème avec le fichier `.infra/local/mongo_keyfile` lors du démarrage du container de `mongodb` (vous auriez des erreurs dans les logs du démarrage du container). - -Si c'est le cas, vérifiez que les droits du ficher sont bien `440` pour MacOS et `400` pour Linux et que le fichier appartient à l'utilisateur lançant `docker`. - -```bash -yarn seed yarn dev ``` @@ -44,8 +41,6 @@ Vous pouvez maintenant accéder à l'application via l'URL [http://localhost:300 Vous pouvez maintenant accéder à l'API via l'URL [http://localhost:5001](http://localhost:5000) -Vous pouvez maintenant accéder au SMTP via l'URL [http://localhost:8025](http://localhost:8025) - ## Détails des commandes globales Les principales opérations sont regroupées dans le `package.json`. @@ -80,10 +75,6 @@ La `cli` du server s'éxécute sur le fichier compilé `server/dist/index.js` ai Commandes: - `yarn cli --help`: List l'ensemble des commandes disponibles -- `yarn cli seed`: Seed de la database -- `yarn cli migrations:status`: Vérification du status des migrations -- `yarn cli migrations:up`: Execution des migrations -- `yarn cli migrations:create`: Creation d'une nouvelle migration ### Lancement de l'application @@ -99,47 +90,6 @@ Lance le server en dev indépendamment de la stack Lance l'ui en dev indépendamment de la stack -### Gestion des services docker - -Lance les services docker en local - -```bash - yarn services:start -``` - ---- - -Stopper les services docker en local - -```bash - yarn services:stop -``` - ---- - -Supprimer les services docker en local - -```bash - yarn services:clean -``` - -### Hydratation du projet en local - -```bash - yarn seed -``` - -Pour créer des jeux de test facilement il suffit de lancer les commandes suivante. -Applique la base de données seed sur la base de données cible (par défaut la base de données locale) - ---- - -Mise à jour de la base de données seed depuis votre local - -```bash - yarn seed:update -``` - ### Deploiement depuis l'environnement local Deploie l'application sur l'environnement cible @@ -150,14 +100,6 @@ Deploie l'application sur l'environnement cible > Optionel si vous avez [configuré 1password](./1password.md#automatisation-de-ansible) -### Gestion des migrations - -Cli pour créer une migration - -```bash - yarn migration:create -d -``` - ### Talisman Ajouter une exception à talisman diff --git a/docs/infrastructure.md b/docs/infrastructure.md index b28f012..7fa9961 100644 --- a/docs/infrastructure.md +++ b/docs/infrastructure.md @@ -2,4 +2,3 @@ - [Architecture](./infrastructure/architecture.md) - [Gestion de l'infrastructure](./manage.md) -- [Environment de Preview](./preview.md) diff --git a/docs/infrastructure/architecture.md b/docs/infrastructure/architecture.md index 745f124..ac705f6 100644 --- a/docs/infrastructure/architecture.md +++ b/docs/infrastructure/architecture.md @@ -214,7 +214,3 @@ Ainsi, avec Fluentd, nous avons la flexibilité d'enrichir, structurer et transf La recette est similaire à l'environnement de production excepté que l'environnement intègre un serveur SMTP pour la gestion des emails. Il est possible d'accéder à l'interface via [https://bal-recette.apprentissage.beta.gouv.fr/smtp/](https://bal-recette.apprentissage.beta.gouv.fr/smtp/) - -## Preview - -Pour plus d'informations concernant l'environnement de recette veuillez vous référer à la [documentation dédiée](./infrastructure/preview.md). diff --git a/docs/infrastructure/preview.md b/docs/infrastructure/preview.md deleted file mode 100644 index 2ffce75..0000000 --- a/docs/infrastructure/preview.md +++ /dev/null @@ -1,5 +0,0 @@ -# Environnement de Preview - -- Multi docker compose -- Project structure -- Cleanup diff --git a/package.json b/package.json index 481761b..6d24fed 100644 --- a/package.json +++ b/package.json @@ -23,21 +23,12 @@ }, "scripts": { "setup": ".bin/mna init:env", - "setup:mongodb": "docker compose exec -it mongodb mongosh --eval \"try { rs.status().ok } catch (e) { if (e.code === 94) {rs.initiate();} else {throw e} }\" --quiet", - "dev": "yarn services:start; yarn foreach:parallel run dev", + "dev": "yarn foreach:parallel run dev", "cli": "yarn workspace server cli", - "seed": ".bin/mna seed:apply", "deploy": ".bin/mna deploy", "build": "yarn foreach:seq run build", - "migrations:status": "yarn cli migrations:status", - "migrations:up": "yarn cli migrations:up", - "migrations:create": "yarn cli migrations:create", "server:dev": "yarn workspace server dev", "ui:dev": "yarn workspace ui dev", - "services:start": "docker compose up --remove-orphans -d --wait", - "services:stop": "docker compose down", - "services:clean": "yarn services:stop; docker system prune --volumes", - "seed:update": ".bin/mna seed:update", "lint": "eslint --ignore-path .gitignore --cache --ext .js,.jsx,.ts,.tsx .", "lint:fix": "yarn lint --fix", "prettier:fix": "prettier --write -u .", @@ -46,9 +37,6 @@ "release:interactive": ".bin/mna release:interactive", "postinstall": "husky install", "talisman:add-exception": "yarn node-talisman --githook pre-commit -i", - "e2e": "cypress open", - "e2e:headless": "cypress run", - "e2e:convert": "node cypress/convertRecords.mjs", "test": "vitest", "test:ci": "yarn test --run", "test:ci:coverage": "yarn test:ci --coverage.include='ui' --coverage.include='server/src' --coverage.include='shared' --coverage.provider='v8' --coverage.enabled --coverage.all --coverage.exclude='**/tests' --coverage.exclude='**/.next'", @@ -63,18 +51,15 @@ "devDependencies": { "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", - "@cypress/chrome-recorder": "^2.3.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/exec": "^6.0.3", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "@vitest/coverage-v8": "^0.34.2", "commander": "^10.0.1", - "cypress": "^12.17.4", "eslint": "^8.47.0", "eslint-config-next": "^13.4.17", "eslint-import-resolver-typescript": "^3.6.0", - "eslint-plugin-cypress": "^2.14.0", "eslint-plugin-import": "^2.28.0", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-mocha": "^10.1.0", diff --git a/server/.env.test b/server/.env.test index 2140607..f389939 100644 --- a/server/.env.test +++ b/server/.env.test @@ -3,19 +3,5 @@ SERVER_PORT=5000 PUBLIC_VERSION=0.0.1 ENV=test PUBLIC_URL=http://localhost -EMAIL=mail@mail.com -MONGODB_URI=mongodb://__system:password@localhost:27017/contrat-test-VITEST_POOL_ID?retryWrites=true&w=1&journal=false&directConnection=true&authSource=local LOG_TYPE=console LOG_LEVEL=none -SESSION_SECRET=mysecretmysecretmysecretmysecret -SESSION_COOKIE_SECURE=false -AUTH_USER_JWT_SECRET=jwtsecret -AUTH_PASSWORD_JWT_SECRET=jwtsecret -AUTH_HASH_ROUNDS=1000 -SMTP_HOST=localhost -SMTP_PORT=1025 -SMTP_SECURE=false -SMTP_WEBHOOK_KEY=none -SMTP_AUTH_USER=test -SMTP_AUTH_PASS=test - diff --git a/server/package.json b/server/package.json index 4283858..05dad27 100644 --- a/server/package.json +++ b/server/package.json @@ -48,7 +48,6 @@ "lodash-es": "^4.17.21", "migrate-mongo": "^10.0.0", "mjml": "^4.14.1", - "mongodb": "^5.7.0", "nodemailer": "^6.9.4", "nodemailer-html-to-text": "^3.2.0", "pdf-lib": "^1.17.1", @@ -56,8 +55,7 @@ "query-string": "^9.0.0", "rate-limiter-flexible": "^2.4.2", "shared": "workspace:*", - "zod": "^3.22.4", - "zod-mongodb-schema": "^1.0.0" + "zod": "^3.22.4" }, "devDependencies": { "@types/adm-zip": "^0.5.5", diff --git a/server/src/commands.ts b/server/src/commands.ts index aa1ef62..c56c0ce 100644 --- a/server/src/commands.ts +++ b/server/src/commands.ts @@ -2,17 +2,13 @@ import { setMaxListeners } from "node:events"; import { captureException } from "@sentry/node"; import { program } from "commander"; -import { addJob, startJobProcessor } from "job-processor"; import HttpTerminator from "lil-http-terminator"; import logger from "@/common/logger"; -import { closeMongodbConnection } from "@/common/utils/mongodbUtils"; import createServer from "@/modules/server/server"; import { closeMemoryCache } from "./common/apis/client"; -import { closeMailer } from "./common/services/mailer/mailer"; import { closeSentry, initSentryProcessor } from "./common/services/sentry/sentry"; -import { sleep } from "./common/utils/asyncUtils"; import config from "./config"; program @@ -30,8 +26,6 @@ program }) .hook("postAction", async () => { closeMemoryCache(); - await closeMailer(); - await closeMongodbConnection(); await closeSentry(); setTimeout(() => { @@ -41,12 +35,6 @@ program }, 60_000).unref(); }); -async function startProcessor(signal: AbortSignal) { - logger.info(`Process jobs queue - start`); - await startJobProcessor(signal); - logger.info(`Processor shut down`); -} - function createProcessExitSignal() { const abortController = new AbortController(); @@ -78,9 +66,8 @@ function createProcessExitSignal() { program .command("start") - .option("--withProcessor", "Exécution du processor également") .description("Démarre le serveur HTTP") - .action(async ({ withProcessor = false }) => { + .action(async () => { try { const signal = createProcessExitSignal(); @@ -113,10 +100,6 @@ program }), ]; - if (withProcessor) { - tasks.push(startProcessor(signal)); - } - await Promise.all(tasks); } catch (err) { logger.error(err); @@ -125,81 +108,6 @@ program } }); -program - .command("job_processor:start") - .description("Run job processor") - .action(async () => { - const signal = createProcessExitSignal(); - if (config.disable_processors) { - // The processor will exit, and be restarted by docker every day - await sleep(24 * 3_600_000, signal); - return; - } - - await startProcessor(signal); - }); - -function createJobAction(name: string) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return async (options: any) => { - try { - const { queued = false, ...payload } = options; - const exitCode = await addJob({ - name, - queued, - payload, - }); - - if (exitCode) { - program.error("Command failed", { exitCode }); - } - } catch (err) { - logger.error(err); - program.error("Command failed", { exitCode: 2 }); - } - }; -} - -program - .command("users:create") - .description("Créer un utilisateur") - .requiredOption("-e, --email ", "Email de l'utilisateur") - .requiredOption("-p, --password ", "Mot de passe de l'utilisateur") - .option("-a, --is_admin", "administrateur", false) - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("users:create")); - -program - .command("db:validate") - .description("Validate Documents") - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("db:validate")); - -program - .command("migrations:up") - .description("Run migrations up") - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("migrations:up")); - -program - .command("migrations:status") - .description("Check migrations status") - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("migrations:status")); - -program - .command("migrations:create") - .description("Run migrations create") - .requiredOption("-d, --description ", "description") - .action(createJobAction("migrations:create")); - -program - .command("indexes:recreate") - .description("Drop and recreate indexes") - .option("-d, --drop", "Drop indexes before recreating them") - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("indexes:recreate")); - program.hook("preAction", (_, actionCommand) => { const command = actionCommand.name(); // on définit le module du logger en global pour distinguer les logs des jobs diff --git a/server/src/common/services/mailer/mailer.ts b/server/src/common/services/mailer/mailer.ts deleted file mode 100644 index 2a4c82d..0000000 --- a/server/src/common/services/mailer/mailer.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { internal } from "@hapi/boom"; -import { captureException } from "@sentry/node"; -import ejs from "ejs"; -import { omit } from "lodash-es"; -import mjml from "mjml"; -import nodemailer from "nodemailer"; -import SMTPTransport from "nodemailer/lib/smtp-transport"; -import { htmlToText } from "nodemailer-html-to-text"; -import { zRoutes } from "shared"; -import { IEmailEvent } from "shared/models/email_event.model"; -import { ITemplate } from "shared/models/email_event/email_templates"; -import { assertUnreachable } from "shared/utils/assertUnreachable"; - -import config from "@/config"; - -import { - addEmailError, - createEmailEvent, - isUnsubscribed, - setEmailMessageId, -} from "../../../modules/actions/emails.actions"; -import { generateAccessToken, generateScope } from "../../../security/accessTokenService"; -import logger from "../../logger"; -import { getStaticFilePath } from "../../utils/getStaticFilePath"; -import { serializeEmailTemplate } from "../../utils/jwtUtils"; - -let transporter: nodemailer.Transporter | null = null; - -export function closeMailer() { - transporter?.close?.(); - transporter = null; -} - -export function initMailer() { - const settings = { ...config.smtp, secure: false }; - const needsAuthentication = !!settings.auth.user; - // @ts-expect-error - transporter = nodemailer.createTransport(needsAuthentication ? settings : omit(settings, ["auth"])); - transporter.use("compile", htmlToText()); -} - -async function sendEmailMessage(template: ITemplate, emailEvent: IEmailEvent | null): Promise { - if (await isUnsubscribed(template.to)) { - return null; - } - if (!transporter) { - throw internal("mailer is not initialised"); - } - - const { messageId } = await transporter.sendMail({ - from: `${config.email_from} <${config.email}>`, - to: template.to, - subject: getEmailSubject(template), - html: await renderEmail(template, emailEvent), - list: { - help: "https://mission-apprentissage.gitbook.io/general/les-services-en-devenir/accompagner-les-futurs-apprentis", // TODO [metier/tech] - unsubscribe: getUnsubscribeActionLink(template), - }, - }); - - return messageId; -} - -export async function sendEmail(template: T): Promise { - const emailEvent = await createEmailEvent(template); - - try { - const messageId = await sendEmailMessage(template, emailEvent); - if (messageId) { - await setEmailMessageId(emailEvent, messageId); - } - } catch (err) { - captureException(err); - logger.error({ err, template: template.name }, "error sending email"); - await addEmailError(emailEvent, { - type: "fatal", - message: err.message, - }); - } -} - -export function getEmailSubject(template: T): string { - switch (template.name) { - case "reset_password": - return "Réinitialisation du mot de passe"; - default: - assertUnreachable(template.name); - } -} - -export function getPublicUrl(path: string) { - return `${config.publicUrl}${path}`; -} - -function getPreviewActionLink(template: ITemplate) { - return getPublicUrl(`/api/emails/preview?data=${serializeEmailTemplate(template)}`); -} - -function getUnsubscribeActionLink(template: ITemplate) { - return getPublicUrl(`/api/emails/unsubscribe?data=${serializeEmailTemplate(template)}`); -} - -function getMarkAsOpenedActionLink(emailEvent: IEmailEvent | null) { - if (!emailEvent) { - return null; - } - - const token = generateAccessToken({ email: emailEvent.template.to }, [ - generateScope({ - schema: zRoutes.get["/emails/:id/markAsOpened"], - options: "all", - resources: {}, - }), - ]); - - return getPublicUrl(`/api/emails/${emailEvent._id.toString()}/markAsOpened?token=${token}`); -} - -export async function renderEmail(template: ITemplate, emailEvent: IEmailEvent | null) { - const templateFile = getStaticFilePath(`./emails/${template.name}.mjml.ejs`); - - const buffer = await ejs.renderFile(templateFile, { - template, - actions: { - unsubscribe: getUnsubscribeActionLink(template), - preview: getPreviewActionLink(template), - markAsOpened: getMarkAsOpenedActionLink(emailEvent), - }, - utils: { getPublicUrl }, - }); - - const { html } = mjml(buffer.toString(), { minify: true }); - return html; -} diff --git a/server/src/common/services/sentry/sentry.ts b/server/src/common/services/sentry/sentry.ts index 2755193..d8db2e0 100644 --- a/server/src/common/services/sentry/sentry.ts +++ b/server/src/common/services/sentry/sentry.ts @@ -32,50 +32,9 @@ export async function closeSentry(): Promise { await Sentry.close(2_000); } -type UserData = { - id?: string | number; - username: string; - email?: string; -} & Record; - -function extractUserData(request: FastifyRequest): UserData { - const user = request.user; - - if (!user) { - // @ts-expect-error - return { - segment: "anonymous", - }; - } - - if (user.type === "token") { - const identity = user.value.identity; - return { - segment: "access-token", - id: identity.email, - email: identity.email, - username: identity.email, - }; - } - - const data: UserData = { - segment: "session", - id: user.value._id.toString(), - username: user.value.email ?? user.value._id.toString(), - type: user.value.is_admin ? "admin" : "standard", - }; - - if (user.value.email) { - data.email = user.value.email; - } - - return data; -} - export function initSentryFastify(app: Server) { const options: FastifySentryOptions = { setErrorHandler: false, - extractUserData: extractUserData, extractRequestData: (request: FastifyRequest) => { return { headers: request.headers, diff --git a/server/src/common/utils/asyncUtils.ts b/server/src/common/utils/asyncUtils.ts index a4b0cb8..8e4fec5 100644 --- a/server/src/common/utils/asyncUtils.ts +++ b/server/src/common/utils/asyncUtils.ts @@ -5,22 +5,3 @@ export async function timeout(promise: Promise, millis: number): Promise clearTimeout(timeoutID)); } - -export async function sleep(durationMs: number, signal?: AbortSignal): Promise { - await new Promise((resolve, reject) => { - let timeout: NodeJS.Timeout | null = null; - - const listener = () => { - if (timeout) clearTimeout(timeout); - reject(signal?.reason); - }; - - timeout = setTimeout(() => { - signal?.removeEventListener("abort", listener); - - resolve(); - }, durationMs); - - signal?.addEventListener("abort", listener); - }); -} diff --git a/server/src/common/utils/cryptoUtils.ts b/server/src/common/utils/cryptoUtils.ts deleted file mode 100644 index cbaede5..0000000 --- a/server/src/common/utils/cryptoUtils.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { internal } from "@hapi/boom"; -import crypto from "crypto"; - -export function generateKey(size = 32, format: BufferEncoding = "base64") { - const buffer = crypto.randomBytes(size); - return buffer.toString(format); -} - -export function generateSecretHash(key: string) { - const salt = crypto.randomBytes(8).toString("hex"); - const buffer = crypto.scryptSync(key, salt, 64); - return `${buffer.toString("hex")}.${salt}`; -} - -export function compareKeys(storedKey: string, suppliedKey: string) { - const [hashedPassword, salt] = storedKey.split("."); - - if (!hashedPassword || !salt) { - throw internal("compareKeys: invalid storedKey"); - } - - const buffer = crypto.scryptSync(suppliedKey, salt, 64); - return crypto.timingSafeEqual(Buffer.from(hashedPassword, "hex"), buffer); -} - -// USAGE -// const key = generateKey(); // send to user: Jj0fmQUis7xKJ6oge4r1fN4em7xJ+hILrgubKlG6PLA= -// const secretHash = generateSecretHash(key); // save in db: c10c7e79fc496144ee245d9dcbe52d9d3910c2a514af1cfe8afda9ea655815efed5bd2a793b31bf923fe47d212bab7896cd527c720849678077e34cdd6fec0a2.2f717b397644fdcc -// VERIF => compareKeys(secretHash, key) diff --git a/server/src/common/utils/jwtUtils.ts b/server/src/common/utils/jwtUtils.ts deleted file mode 100644 index 9355b40..0000000 --- a/server/src/common/utils/jwtUtils.ts +++ /dev/null @@ -1,61 +0,0 @@ -import jwt, { SignOptions } from "jsonwebtoken"; -import { zRoutes } from "shared"; -import { ITemplate, zTemplate } from "shared/models/email_event/email_templates"; -import { IUser } from "shared/models/user.model"; - -import config from "@/config"; - -import { generateAccessToken, generateScope } from "../../security/accessTokenService"; - -interface ICreateTokenOptions { - secret?: string; - expiresIn?: string; - payload?: string | Buffer | object; -} - -type TokenType = "user" | "resetPasswordToken"; - -const createToken = (type: TokenType, subject: string | null = null, options: ICreateTokenOptions = {}) => { - const defaults = config.auth[type]; - const secret = options.secret ?? defaults.jwtSecret; - const expiresIn = options.expiresIn ?? defaults.expiresIn; - const payload = options.payload ?? {}; - - const opts: SignOptions = { - issuer: config.productName, - expiresIn: expiresIn, - }; - if (subject) { - opts.subject = subject; - } - return jwt.sign(payload, secret, opts); -}; - -export function createResetPasswordToken(user: IUser) { - return generateAccessToken(user, [ - generateScope({ - schema: zRoutes.post["/auth/reset-password"], - options: "all", - resources: {}, - }), - ]); -} - -export function serializeEmailTemplate(template: ITemplate): string { - // We do not set expiry as the result is not used as a token but as serialized data - return jwt.sign(template, config.auth.user.jwtSecret, { - issuer: config.productName, - }); -} - -export function deserializeEmailTemplate(data: string): ITemplate { - return zTemplate.parse(jwt.verify(data, config.auth.user.jwtSecret)); -} - -export function createUserTokenSimple(options = {}) { - return createToken("user", null, options); -} - -export const decodeToken = (token: string, type: TokenType = "user") => { - return jwt.verify(token, config.auth[type].jwtSecret); -}; diff --git a/server/src/common/utils/mongodbUtils.ts b/server/src/common/utils/mongodbUtils.ts deleted file mode 100644 index 32d03ce..0000000 --- a/server/src/common/utils/mongodbUtils.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { captureException } from "@sentry/node"; -import { Collection, CollectionInfo, MongoClient, MongoServerError } from "mongodb"; -import { CollectionName, IModelDescriptor } from "shared/models/common"; -import { IDocumentMap, modelDescriptors } from "shared/models/models"; -import { zodToMongoSchema } from "zod-mongodb-schema"; - -import logger from "@/common/logger"; - -import config from "../../config"; -import { sleep } from "./asyncUtils"; - -let mongodbClient: MongoClient | null = null; - -export const ensureInitialization = () => { - if (!mongodbClient) { - throw new Error("Database connection does not exist. Please call connectToMongodb before."); - } - return mongodbClient; -}; - -/** - * @param {string} uri - * @returns client - */ -export const connectToMongodb = async (uri: string) => { - const client = new MongoClient(uri, { - appName: config.productName, - }); - - client.on("connectionPoolReady", () => { - logger.info("MongoDB reconnected"); - mongodbClient = client; - }); - - client.on("connectionPoolClosed", () => { - logger.warn("MongoDB closed"); - mongodbClient = null; - }); - - await client.connect(); - mongodbClient = client; - logger.info("Connected to MongoDB"); - - return client; -}; - -export const getMongodbClient = () => mongodbClient; - -export const closeMongodbConnection = async () => { - logger.warn("Closing MongoDB"); - // Let 100ms for possible callback cleanup to register tasks in mongodb queue - await sleep(200); - return mongodbClient?.close(); -}; - -export const getDatabase = () => { - return ensureInitialization().db(); -}; - -export const getDbCollection = (name: K): Collection => { - return ensureInitialization().db().collection(name); -}; - -export const getCollectionList = () => { - return ensureInitialization().db().listCollections().toArray(); -}; - -export const getDbCollectionIndexes = async (name: CollectionName) => { - return await ensureInitialization().db().collection(name).indexes(); -}; - -/** - * Création d'une collection si elle n'existe pas - * @param {string} collectionName - */ -const createCollectionIfDoesNotExist = async (collectionName: CollectionName) => { - const db = getDatabase(); - const collectionsInDb = await db.listCollections().toArray(); - const collectionExistsInDb = collectionsInDb.map(({ name }) => name).includes(collectionName); - - if (!collectionExistsInDb) { - try { - await db.createCollection(collectionName); - } catch (err) { - if ((err as MongoServerError).codeName !== "NamespaceExists") { - throw err; - } - } - } -}; - -/** - * Vérification de l'existence d'une collection à partir de la liste des collections - * @param {*} collectionsInDb - * @param {*} collectionName - * @returns - */ -export const collectionExistInDb = (collectionsInDb: CollectionInfo[], collectionName: string) => - collectionsInDb.map(({ name }: { name: string }) => name).includes(collectionName); - -/** - * Config de la validation - * @param {*} modelDescriptors - */ -export const configureDbSchemaValidation = async (modelDescriptors: IModelDescriptor[]) => { - const db = getDatabase(); - ensureInitialization(); - await Promise.all( - modelDescriptors.map(async ({ collectionName, zod }) => { - await createCollectionIfDoesNotExist(collectionName); - - const convertedSchema = zodToMongoSchema(zod); - - try { - await db.command({ - collMod: collectionName, - validationLevel: "strict", - validationAction: "error", - validator: { - $jsonSchema: { - title: `${collectionName} validation schema`, - ...convertedSchema, - }, - }, - }); - } catch (error) { - captureException(error); - logger.error(error); - } - }) - ); -}; - -/** - * Clear de toutes les collections - * @returns - */ -export const clearAllCollections = async () => { - const collections = await getDatabase().collections(); - return Promise.all(collections.map((c) => c.deleteMany({}))); -}; - -/** - * Clear d'une collection - * @param {string} name - * @returns - */ -export async function clearCollection(name: string) { - ensureInitialization(); - await getDatabase().collection(name).deleteMany({}); -} - -export const createIndexes = async () => { - for (const descriptor of modelDescriptors) { - if (!descriptor.indexes) { - return; - } - logger.info(`Create indexes for collection ${descriptor.collectionName}`); - await Promise.all( - descriptor.indexes.map(async ([index, options]) => { - try { - await getDbCollection(descriptor.collectionName).createIndex(index, options); - } catch (err) { - captureException(err); - logger.error(`Error creating indexes for ${descriptor.collectionName}: ${err}`); - } - }) - ); - } -}; - -export const dropIndexes = async () => { - const collections = (await getCollectionList()).map((collection) => collection.name); - for (const descriptor of modelDescriptors) { - logger.info(`Drop indexes for collection ${descriptor.collectionName}`); - if (collections.includes(descriptor.collectionName)) { - await getDbCollection(descriptor.collectionName).dropIndexes(); - } - } -}; diff --git a/server/src/config.ts b/server/src/config.ts index a4f3f14..f1414ce 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -4,50 +4,12 @@ const config = { productName: env.get("PUBLIC_PRODUCT_NAME").required().asString(), port: env.get("SERVER_PORT").required().asPortNumber(), version: env.get("PUBLIC_VERSION").required().asString(), - env: env.get("ENV").required().asEnum(["local", "recette", "production", "preview", "test"]), + env: env.get("ENV").required().asEnum(["local", "recette", "production", "test"]), publicUrl: env.get("PUBLIC_URL").required().asString(), - email: env.get("EMAIL").required().asString(), - email_from: "Mission Apprentissage", - mongodb: { - uri: env.get("MONGODB_URI").required().asString(), - }, log: { type: env.get("LOG_TYPE").required().asString(), level: env.get("LOG_LEVEL").required().asString(), }, - session: { - secret: env.get("SESSION_SECRET").required().asString(), - cookieName: "contrat_session", - cookie: { - maxAge: 30 * 24 * 3600000, - httpOnly: true, - sameSite: "lax" as const, - path: "/", - secure: env.get("SESSION_COOKIE_SECURE").default("true").asBool(), - }, - }, - auth: { - user: { - jwtSecret: env.get("AUTH_USER_JWT_SECRET").required().asString(), - expiresIn: "7d", - }, - resetPasswordToken: { - jwtSecret: env.get("AUTH_PASSWORD_JWT_SECRET").required().asString(), - expiresIn: "1h", - }, - hashRounds: env.get("AUTH_HASH_ROUNDS").required().asIntPositive(), - }, - smtp: { - host: env.get("SMTP_HOST").required().asString(), - port: env.get("SMTP_PORT").required().asString(), - secure: env.get("SMTP_SECURE").asBool(), - webhookKey: env.get("SMTP_WEBHOOK_KEY").required().asString(), - auth: { - user: env.get("SMTP_AUTH_USER").required().asString(), - pass: env.get("SMTP_AUTH_PASS").required().asString(), - }, - }, - disable_processors: env.get("DISABLE_PROCESSORS").default("false").asBool(), apiEntreprise: env.get("MNA_CONTRAT_API_ENTREPRISE_SECRET").asString(), }; diff --git a/server/src/db/migrations/20230511154647-example.ts b/server/src/db/migrations/20230511154647-example.ts deleted file mode 100644 index 75612d2..0000000 --- a/server/src/db/migrations/20230511154647-example.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Db, MongoClient } from "mongodb"; - -export const up = async (_db: Db, _client: MongoClient) => { - // TODO write your migration here. - // See https://github.com/seppevs/migrate-mongo/#creating-a-new-migration-script - // Example: -}; diff --git a/server/src/index.ts b/server/src/index.ts index fa4b79b..70fb32b 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,24 +1,10 @@ import { captureException } from "@sentry/node"; -import { modelDescriptors } from "shared/models/models"; import { startCLI } from "@/commands"; import logger from "@/common/logger"; -import { configureDbSchemaValidation, connectToMongodb } from "@/common/utils/mongodbUtils"; -import config from "@/config"; - -import { initMailer } from "./common/services/mailer/mailer"; -import { setupJobProcessor } from "./modules/jobs/jobs"; (async function () { try { - await connectToMongodb(config.mongodb.uri); - await configureDbSchemaValidation(modelDescriptors); - - // We need to setup even for server to be able to call addJob - await setupJobProcessor(); - - await initMailer(); - startCLI(); } catch (err) { captureException(err); diff --git a/server/src/modules/actions/auth.actions.ts b/server/src/modules/actions/auth.actions.ts deleted file mode 100644 index 3994620..0000000 --- a/server/src/modules/actions/auth.actions.ts +++ /dev/null @@ -1,47 +0,0 @@ -import logger from "@/common/logger"; -import { sendEmail } from "@/common/services/mailer/mailer"; -import { createResetPasswordToken } from "@/common/utils/jwtUtils"; - -import { getDbCollection } from "../../common/utils/mongodbUtils"; -import { IAccessToken } from "../../security/accessTokenService"; -import { hashPassword, verifyPassword } from "../server/utils/password.utils"; -import { updateUser } from "./users.actions"; - -export const verifyEmailPassword = async (email: string, password: string) => { - const user = await getDbCollection("users").findOne({ email }); - - if (!user) { - return; - } - - const match = verifyPassword(password, user.password); - - if (!match) { - return; - } - - return user; -}; - -export const sendResetPasswordEmail = async (email: string) => { - const user = await getDbCollection("users").findOne({ email }); - - if (!user) { - logger.warn({ email }, "forgot-password: missing user"); - return; - } - - const token = createResetPasswordToken(user); - - await sendEmail({ - name: "reset_password", - to: email, - resetPasswordToken: token, - }); -}; - -export const resetPassword = async (token: IAccessToken, password: string) => { - const hashedPassword = hashPassword(password); - - await updateUser(token.identity.email, { password: hashedPassword }); -}; diff --git a/server/src/modules/actions/emails.actions.ts b/server/src/modules/actions/emails.actions.ts deleted file mode 100644 index b8345d9..0000000 --- a/server/src/modules/actions/emails.actions.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { ObjectId } from "mongodb"; -import { IEmailError, IEmailEvent } from "shared/models/email_event.model"; - -import { getDbCollection } from "@/common/utils/mongodbUtils"; - -export async function createEmailEvent(template: IEmailEvent["template"]) { - const now = new Date(); - - const event: IEmailEvent = { - _id: new ObjectId(), - email: template.to, - template, - opened_at: null, - delivered_at: null, - created_at: now, - updated_at: now, - messageId: null, - errors: [], - }; - - await getDbCollection("email_events").insertOne(event); - return event; -} - -export function setEmailMessageId(emailEvent: IEmailEvent, messageId: string) { - return getDbCollection("email_events").findOneAndUpdate( - { _id: emailEvent._id }, - { - $set: { - updated_at: new Date(), - messageId, - }, - }, - { returnDocument: "after" } - ); -} - -export function addEmailError(filter: Pick | Pick, err: IEmailError) { - return getDbCollection("email_events").findOneAndUpdate( - filter, - { - $push: { - errors: err, - }, - $set: { - updated_at: new Date(), - }, - }, - { returnDocument: "after" } - ); -} - -export async function markEmailAsDelivered(messageId: string) { - const now = new Date(); - await getDbCollection("email_events").findOneAndUpdate( - { messageId }, - { - $set: { - delivered_at: now, - updated_at: now, - }, - } - ); -} - -export async function markEmailAsFailed(messageId: string, type: IEmailError["type"]) { - return addEmailError({ messageId }, { type }); -} - -export async function markEmailAsOpened(id: ObjectId) { - const now = new Date(); - await getDbCollection("email_events").findOneAndUpdate( - { _id: id }, - { - $set: { - opened_at: now, - updated_at: now, - }, - } - ); -} - -export async function unsubscribe(email: string) { - const now = new Date(); - - await getDbCollection("email_denied").updateOne( - { - email, - }, - { - $set: { - reason: "unsubscribe", - updated_at: now, - }, - $setOnInsert: { - email, - created_at: now, - }, - }, - { upsert: true } - ); -} - -export async function isUnsubscribed(email: string): Promise { - const denied = await getDbCollection("email_denied").findOne( - { - email, - }, - { projection: { _id: 0, email: 1 } } - ); - - return denied !== null; -} diff --git a/server/src/modules/actions/sessions.actions.ts b/server/src/modules/actions/sessions.actions.ts deleted file mode 100644 index bc80d20..0000000 --- a/server/src/modules/actions/sessions.actions.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { FastifyReply, FastifyRequest } from "fastify"; -import jwt from "jsonwebtoken"; -import { Filter, FindOptions, ObjectId } from "mongodb"; -import { ISession } from "shared/models/session.model"; - -import { getDbCollection } from "@/common/utils/mongodbUtils"; - -import config from "../../config"; - -type TCreateSession = Pick; - -async function createSession(data: TCreateSession) { - const now = new Date(); - - const session = { - _id: new ObjectId(), - ...data, - updated_at: now, - created_at: now, - expires_at: new Date(now.getTime() + config.session.cookie.maxAge), - }; - - await getDbCollection("sessions").insertOne(session); - - return session; -} - -async function getSession(filter: Filter, options?: FindOptions): Promise { - return getDbCollection("sessions").findOne(filter, options); -} - -async function deleteSession(token: string) { - await getDbCollection("sessions").deleteMany({ token }); -} - -function createSessionToken(email: string) { - return jwt.sign({ email }, config.auth.user.jwtSecret, { - issuer: config.publicUrl, - expiresIn: config.auth.user.expiresIn, - subject: email, - }); -} - -async function startSession(email: string, res: FastifyReply) { - const token = createSessionToken(email); - await createSession({ token }); - res.setCookie(config.session.cookieName, token, config.session.cookie); -} - -async function stopSession(req: FastifyRequest, res: FastifyReply) { - const token = req.cookies[config.session.cookieName]; - - if (token) { - await deleteSession(token); - } - - res.clearCookie(config.session.cookieName, config.session.cookie); -} - -export { getSession, startSession, stopSession, createSessionToken, createSession }; diff --git a/server/src/modules/actions/users.actions.ts b/server/src/modules/actions/users.actions.ts deleted file mode 100644 index 72e5353..0000000 --- a/server/src/modules/actions/users.actions.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { ObjectId } from "mongodb"; -import { IUser, IUserCreate } from "shared/models/user.model"; - -import { getDbCollection } from "@/common/utils/mongodbUtils"; - -import { generateKey, generateSecretHash } from "../../common/utils/cryptoUtils"; -import { createUserTokenSimple } from "../../common/utils/jwtUtils"; -import { hashPassword } from "../server/utils/password.utils"; - -export const createUser = async (data: IUserCreate) => { - const _id = new ObjectId(); - - const password = hashPassword(data.password); - const now = new Date(); - const user: IUser = { - ...data, - _id, - password, - api_key: null, - api_key_used_at: null, - updated_at: now, - created_at: now, - }; - - await getDbCollection("users").insertOne(user); - - return user; -}; - -export const updateUser = async (email: IUser["email"], data: Partial): Promise => { - await getDbCollection("users").findOneAndUpdate( - { - email, - }, - { - $set: { ...data, updated_at: new Date() }, - } - ); -}; - -export const generateApiKey = async (user: IUser) => { - const generatedKey = generateKey(); - const secretHash = generateSecretHash(generatedKey); - - await updateUser(user.email, { api_key: secretHash, api_key_used_at: null }); - - const token = createUserTokenSimple({ - payload: { _id: user._id, api_key: generatedKey }, - expiresIn: "365d", - }); - - return token; -}; diff --git a/server/src/modules/jobs/db/recreateIndexes.ts b/server/src/modules/jobs/db/recreateIndexes.ts deleted file mode 100644 index 3464c8a..0000000 --- a/server/src/modules/jobs/db/recreateIndexes.ts +++ /dev/null @@ -1,12 +0,0 @@ -import logger from "@/common/logger"; -import { createIndexes, dropIndexes } from "@/common/utils/mongodbUtils"; - -export const recreateIndexes = async ({ drop } = { drop: false }) => { - if (drop) { - logger.info("Drop all existing indexes..."); - await dropIndexes(); - } - logger.info("Create all indexes..."); - await createIndexes(); - logger.info("All indexes successfully created !"); -}; diff --git a/server/src/modules/jobs/db/schemaValidation.ts b/server/src/modules/jobs/db/schemaValidation.ts deleted file mode 100644 index e2e050c..0000000 --- a/server/src/modules/jobs/db/schemaValidation.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { captureException } from "@sentry/node"; -import { modelDescriptors } from "shared/models/models"; - -import { getDatabase } from "@/common/utils/mongodbUtils"; - -export async function countInvalidDocuments(collectionName: string): Promise { - const collection = getDatabase().collection(collectionName); - const options = await collection.options(); - - return collection.countDocuments({ $nor: [options.validator] }); -} - -export async function validateDocuments(collectionName: string) { - const invalidCount = await countInvalidDocuments(collectionName); - if (invalidCount > 0) { - const error = new Error(`Collection ${collectionName} contains ${invalidCount} invalid documents`); - captureException(error); - throw error; - } -} - -export async function validateModels(): Promise { - await Promise.all(modelDescriptors.map((d) => validateDocuments(d.collectionName))); -} diff --git a/server/src/modules/jobs/jobs.ts b/server/src/modules/jobs/jobs.ts deleted file mode 100644 index 9a7dc2c..0000000 --- a/server/src/modules/jobs/jobs.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { addJob, initJobProcessor } from "job-processor"; -import { zUserCreate } from "shared/models/user.model"; - -import { - create as createMigration, - status as statusMigration, - up as upMigration, -} from "@/modules/jobs/migrations/migrations"; - -import logger from "../../common/logger"; -import { getDatabase } from "../../common/utils/mongodbUtils"; -import config from "../../config"; -import { createUser } from "../actions/users.actions"; -import { recreateIndexes } from "./db/recreateIndexes"; -import { validateModels } from "./db/schemaValidation"; - -export async function setupJobProcessor() { - return initJobProcessor({ - db: getDatabase(), - logger, - crons: config.env === "preview" || config.env === "local" ? {} : {}, - jobs: { - "users:create": { - handler: async (job) => { - await createUser(zUserCreate.parse(job.payload)); - }, - }, - "indexes:recreate": { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - handler: async (job) => recreateIndexes(job.payload as any), - }, - "db:validate": { - handler: async () => validateModels(), - }, - "migrations:up": { - handler: async () => { - await upMigration(); - // Validate all documents after the migration - await addJob({ name: "db:validate", queued: true }); - return; - }, - }, - "migrations:status": { - handler: async () => { - const pendingMigrations = await statusMigration(); - console.log(`migrations-status=${pendingMigrations === 0 ? "synced" : "pending"}`); - return; - }, - }, - "migrations:create": { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - handler: async (job) => createMigration(job.payload as any), - }, - }, - }); -} diff --git a/server/src/modules/jobs/migrations/migrations.ts b/server/src/modules/jobs/migrations/migrations.ts deleted file mode 100644 index a09f093..0000000 --- a/server/src/modules/jobs/migrations/migrations.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { readFile, writeFile } from "node:fs/promises"; - -import { config, create as mcreate, status as mstatus, up as mup } from "migrate-mongo"; -import path from "path"; - -import { __dirname } from "@/common/utils/esmUtils"; -import { getMongodbClient } from "@/common/utils/mongodbUtils"; - -const myConfig = { - mongodb: { - url: process.env.MONGODB_URI as string, - - // in URL - databaseName: "", - - options: { - useNewUrlParser: true, // removes a deprecation warning when connecting - useUnifiedTopology: true, // removes a deprecating warning when connecting - // connectTimeoutMS: 3600000, // increase connection timeout to 1 hour - // socketTimeoutMS: 3600000, // increase socket timeout to 1 hour - }, - }, - - // The migrations dir, can be an relative or absolute path. Only edit this when really necessary. - migrationsDir: path.join(__dirname(import.meta.url), "./db/migrations"), - - // The mongodb collection where the applied changes are stored. Only edit this when really necessary. - changelogCollectionName: "migrations", - - // The file extension to create migrations and search for in migration dir - migrationFileExtension: ".js", - - // Enable the algorithm to create a checksum of the file contents and use that in the comparison to determin - // if the file should be run. Requires that scripts are coded to be run multiple times. - useFileHash: false, - - // Don't change this, unless you know what you're doing - moduleSystem: "esm", -}; - -export async function up() { - // @ts-ignore - config.set(myConfig); - - await status(); - - const client = getMongodbClient(); - // @ts-ignore - await mup(client.db(), client); -} - -// Show migration status and returns number of pending migrations -export async function status(): Promise { - // @ts-ignore - config.set(myConfig); - const client = getMongodbClient(); - - // @ts-ignore - const migrationStatus = await mstatus(client.db()); - migrationStatus.forEach(({ fileName, appliedAt }) => console.log(fileName, ":", appliedAt)); - - return migrationStatus.filter(({ appliedAt }) => appliedAt === "PENDING").length; -} - -export async function create({ description }: { description: string }) { - // @ts-ignore - config.set({ - ...myConfig, - migrationsDir: "src/db/migrations", - migrationFileExtension: ".ts", - }); - const fileName = await mcreate(description); - const file = `src/db/migrations/${fileName}`; - const content = await readFile(file, { - encoding: "utf-8", - }); - const newContent = - 'import { Db, MongoClient } from "mongodb";\n\n' + - content.replaceAll("async (db, client)", "async (_db: Db, _client: MongoClient)"); - - await writeFile(file, newContent, { encoding: "utf-8" }); - console.log("Created:", fileName); -} diff --git a/server/src/modules/server/admin/user.routes.ts b/server/src/modules/server/admin/user.routes.ts deleted file mode 100644 index c3abe76..0000000 --- a/server/src/modules/server/admin/user.routes.ts +++ /dev/null @@ -1,65 +0,0 @@ -import Boom from "@hapi/boom"; -import { RootFilterOperators } from "mongodb"; -import { zRoutes } from "shared"; -import { IUser, toPublicUser } from "shared/models/user.model"; - -import { getDbCollection } from "../../../common/utils/mongodbUtils"; -import { createUser } from "../../actions/users.actions"; -import { Server } from "../server"; - -export const userAdminRoutes = ({ server }: { server: Server }) => { - server.post( - "/admin/user", - { - schema: zRoutes.post["/admin/user"], - onRequest: [server.auth(zRoutes.post["/admin/user"])], - }, - async (request, response) => { - const user = await createUser(request.body); - - if (!user) { - throw Boom.badImplementation("Impossible de créer l'utilisateur"); - } - - return response.status(200).send(toPublicUser(user)); - } - ); - - server.get( - "/admin/users", - { - schema: zRoutes.get["/admin/users"], - onRequest: [server.auth(zRoutes.get["/admin/users"])], - }, - async (request, response) => { - const filter: RootFilterOperators = {}; - - const { q } = request.query; - - if (q) { - filter.$text = { $search: q }; - } - - const users = await getDbCollection("users").find(filter).toArray(); - - return response.status(200).send(users.map(toPublicUser)); - } - ); - - server.get( - "/admin/users/:id", - { - schema: zRoutes.get["/admin/users/:id"], - onRequest: [server.auth(zRoutes.get["/admin/users/:id"])], - }, - async (request, response) => { - const user = await getDbCollection("users").findOne({ _id: request.params.id }); - - if (!user) { - throw Boom.notFound(); - } - - return response.status(200).send(toPublicUser(user)); - } - ); -}; diff --git a/server/src/modules/server/auth.routes.ts b/server/src/modules/server/auth.routes.ts deleted file mode 100644 index ea0170e..0000000 --- a/server/src/modules/server/auth.routes.ts +++ /dev/null @@ -1,91 +0,0 @@ -import Boom from "@hapi/boom"; -import { zRoutes } from "shared"; -import { IUser, toPublicUser } from "shared/models/user.model"; - -import { getUserFromRequest } from "../../security/authenticationService"; -import { resetPassword, sendResetPasswordEmail, verifyEmailPassword } from "../actions/auth.actions"; -import { startSession, stopSession } from "../actions/sessions.actions"; -import { Server } from "./server"; - -export const authRoutes = ({ server }: { server: Server }) => { - /** - * Récupérer l'utilisateur connecté - */ - server.get( - "/auth/session", - { - schema: zRoutes.get["/auth/session"], - onRequest: [server.auth(zRoutes.get["/auth/session"])], - }, - async (request, response) => { - const user = getUserFromRequest(request, zRoutes.get["/auth/session"]); - return response.status(200).send(toPublicUser(user)); - } - ); - - /** - * Login - */ - server.post( - "/auth/login", - { - schema: zRoutes.post["/auth/login"], - }, - async (request, response) => { - const { email, password } = request.body; - - const user: IUser | undefined = await verifyEmailPassword(email, password); - - if (!user || !user._id) { - throw Boom.forbidden("Identifiants incorrects"); - } - - await startSession(user.email, response); - - return response.status(200).send(toPublicUser(user)); - } - ); - - server.get( - "/auth/logout", - { - schema: zRoutes.get["/auth/logout"], - }, - async (request, response) => { - await stopSession(request, response); - - return response.status(200).send({}); - } - ); - - server.get( - "/auth/reset-password", - { - schema: zRoutes.get["/auth/reset-password"], - }, - async (request, response) => { - await sendResetPasswordEmail(request.query.email); - return response.status(200).send({}); - } - ); - - server.post( - "/auth/reset-password", - { - schema: zRoutes.post["/auth/reset-password"], - onRequest: [server.auth(zRoutes.post["/auth/reset-password"])], - }, - async (request, response) => { - const { password } = request.body; - const user = getUserFromRequest(request, zRoutes.post["/auth/reset-password"]); - - try { - await resetPassword(user, password); - - return response.status(200).send({}); - } catch (error) { - throw Boom.badData("Jeton invalide"); - } - } - ); -}; diff --git a/server/src/modules/server/core.routes.ts b/server/src/modules/server/core.routes.ts index 1891848..e963bdd 100644 --- a/server/src/modules/server/core.routes.ts +++ b/server/src/modules/server/core.routes.ts @@ -2,25 +2,14 @@ import { zRoutes } from "shared"; import config from "@/config"; -import { ensureInitialization } from "../../common/utils/mongodbUtils"; import { Server } from "./server"; export const coreRoutes = ({ server }: { server: Server }) => { server.get("/healthcheck", { schema: zRoutes.get["/healthcheck"] }, async (request, response) => { - ensureInitialization(); response.status(200).send({ name: `${config.productName} Apprentissage API`, version: config.version, env: config.env, }); }); - server.get( - "/healthcheck/sentry", - { - schema: zRoutes.get["/healthcheck/sentry"], - }, - async () => { - throw new Error("testing sentry error"); - } - ); }; diff --git a/server/src/modules/server/emails.routes.ts b/server/src/modules/server/emails.routes.ts deleted file mode 100644 index 4fe03c6..0000000 --- a/server/src/modules/server/emails.routes.ts +++ /dev/null @@ -1,106 +0,0 @@ -import Boom from "@hapi/boom"; -import { zRoutes } from "shared"; -import { IEmailError } from "shared/models/email_event.model"; - -import { renderEmail } from "../../common/services/mailer/mailer"; -import { deserializeEmailTemplate } from "../../common/utils/jwtUtils"; -import config from "../../config"; -import { markEmailAsDelivered, markEmailAsFailed, markEmailAsOpened, unsubscribe } from "../actions/emails.actions"; -import { Server } from "./server"; - -export const emailsRoutes = ({ server }: { server: Server }) => { - server.get( - "/emails/preview", - { - schema: zRoutes.get["/emails/preview"], - }, - async (request, response) => { - const template = deserializeEmailTemplate(request.query.data); - // No need to set markAsOpenedActionLink as the email as already be openned - const html = await renderEmail(template, null); - return response - .header("Content-Type", "text/html") - .status(200) - .send(Buffer.from(html as string)); - } - ); - - server.get( - "/emails/:id/markAsOpened", - { - schema: zRoutes.get["/emails/:id/markAsOpened"], - onRequest: [server.auth(zRoutes.get["/emails/:id/markAsOpened"])], - }, - async (request, response) => { - await markEmailAsOpened(request.params.id); - - return response - .header("Content-Type", "image/gif") - .status(200) - .send(Buffer.from("R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==", "base64")); - } - ); - - server.get( - "/emails/unsubscribe", - { - schema: zRoutes.get["/emails/unsubscribe"], - }, - async (request, response) => { - const template = deserializeEmailTemplate(request.query.data); - - await unsubscribe(template.to); - - return response - .header("Content-Type", "text/html") - .status(200) - .send( - Buffer.from( - ` - - - - Désinscription - - -
-
-

Désinscription

-
- -
- - - - ` - ) - ); - } - ); - - server.post( - "/emails/webhook", - { - schema: zRoutes.post["/emails/webhook"], - }, - async (request, response) => { - const { webhookKey } = request.query; - - if (config.smtp.webhookKey !== webhookKey) { - throw Boom.forbidden("Non autorisé"); - } - - const { event, "message-id": messageId } = request.body; - - if (event === "delivered") { - markEmailAsDelivered(messageId); - } else { - markEmailAsFailed(messageId, event as IEmailError["type"]); - } - - return response.status(200).send(); - } - ); -}; diff --git a/server/src/modules/server/middlewares/authMiddleware.ts b/server/src/modules/server/middlewares/authMiddleware.ts deleted file mode 100644 index ae95399..0000000 --- a/server/src/modules/server/middlewares/authMiddleware.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { - ContextConfigDefault, - FastifyBaseLogger, - FastifyRequest, - FastifyTypeProvider, - FastifyTypeProviderDefault, - preHandlerHookHandler, - RawReplyDefaultExpression, - RawRequestDefaultExpression, - RawServerBase, - RawServerDefault, - RouteGenericInterface, -} from "fastify"; -import { IRouteSchema, SecurityScheme, WithSecurityScheme } from "shared/routes/common.routes"; - -import { authenticationMiddleware } from "@/security/authenticationService"; -import { authorizationnMiddleware } from "@/security/authorisationService"; - -const symbol: unique symbol = Symbol("authStrategy"); - -type AuthMiddleware = { - (req: FastifyRequest): Promise; - [symbol]?: Readonly; -}; - -export function auth(schema: S) { - const authMiddleware: AuthMiddleware = async (req: FastifyRequest) => { - await authenticationMiddleware(schema, req); - await authorizationnMiddleware(schema, req); - }; - - authMiddleware[symbol] = schema.securityScheme; - - return authMiddleware; -} - -export function describeAuthMiddleware(fn: AuthMiddleware): SecurityScheme | null { - return fn[symbol] ?? null; -} - -declare module "fastify" { - interface FastifyInstance< - RawServer extends RawServerBase = RawServerDefault, - RawRequest extends RawRequestDefaultExpression = RawRequestDefaultExpression, - RawReply extends RawReplyDefaultExpression = RawReplyDefaultExpression, - Logger extends FastifyBaseLogger = FastifyBaseLogger, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, - > { - auth< - RouteGeneric extends RouteGenericInterface = RouteGenericInterface, - ContextConfig = ContextConfigDefault, - SchemaCompiler extends FastifySchema = FastifySchema, - >( - scheme: IRouteSchema & WithSecurityScheme - ): preHandlerHookHandler< - RawServer, - RawRequest, - RawReply, - RouteGeneric, - ContextConfig, - SchemaCompiler, - TypeProvider, - Logger - >; - } -} diff --git a/server/src/modules/server/server.ts b/server/src/modules/server/server.ts index 4ad5c4a..12f2e52 100644 --- a/server/src/modules/server/server.ts +++ b/server/src/modules/server/server.ts @@ -1,8 +1,6 @@ import fastifyCookie from "@fastify/cookie"; import fastifyCors from "@fastify/cors"; import fastifyMultipart from "@fastify/multipart"; -import fastifySwagger, { FastifyStaticSwaggerOptions, StaticDocumentSpec } from "@fastify/swagger"; -import fastifySwaggerUi, { FastifySwaggerUiOptions } from "@fastify/swagger-ui"; import Boom from "@hapi/boom"; import fastify, { FastifyBaseLogger, @@ -12,25 +10,18 @@ import fastify, { RawServerDefault, } from "fastify"; import { serializerCompiler, validatorCompiler, ZodTypeProvider } from "fastify-type-provider-zod"; -import { generateOpenApiSchema } from "shared/helpers/openapi/generateOpenapi"; -import { IRouteSchema, WithSecurityScheme } from "shared/routes/common.routes"; import { initSentryFastify } from "../../common/services/sentry/sentry"; import config from "../../config"; -import { userAdminRoutes } from "./admin/user.routes"; -import { authRoutes } from "./auth.routes"; import { cerfaRoutes } from "./cerfa.routes"; import { controlsRoutes } from "./controls.routes"; import { coreRoutes } from "./core.routes"; -import { emailsRoutes } from "./emails.routes"; import { geoRoutes } from "./geo.routes"; -import { auth } from "./middlewares/authMiddleware"; import { errorMiddleware } from "./middlewares/errorMiddleware"; import { logMiddleware } from "./middlewares/logMiddleware"; import { nafRoutes } from "./naf.routes"; import { siretRoutes } from "./siret.routes"; import { tcoRoutes } from "./tco.routes"; -import { userRoutes } from "./user.routes"; export interface Server extends FastifyInstance< @@ -47,32 +38,7 @@ export async function bind(app: Server) { app.setValidatorCompiler(validatorCompiler); app.setSerializerCompiler(serializerCompiler); - const swaggerOpts: FastifyStaticSwaggerOptions = { - mode: "static", - specification: { - document: generateOpenApiSchema( - config.version, - config.env, - config.env === "local" ? "http://localhost:5001/api" : `${config.publicUrl}/api` - ) as StaticDocumentSpec["document"], - }, - }; - await app.register(fastifySwagger, swaggerOpts); - - const swaggerUiOptions: FastifySwaggerUiOptions = { - routePrefix: "/api/documentation", - uiConfig: { - displayOperationId: true, - operationsSorter: "method", - tagsSorter: "alpha", - docExpansion: "list", - deepLinking: false, - }, - }; - await app.register(fastifySwaggerUi, swaggerUiOptions); - app.register(fastifyCookie); - app.decorate("auth", (scheme: S) => auth(scheme)); app.register(fastifyMultipart); app.register(fastifyCors, { @@ -114,10 +80,6 @@ type RegisterRoutes = (opts: { server: Server }) => void; export const registerRoutes: RegisterRoutes = ({ server }) => { coreRoutes({ server }); - authRoutes({ server }); - userRoutes({ server }); - emailsRoutes({ server }); - userAdminRoutes({ server }); cerfaRoutes({ server }); controlsRoutes({ server }); geoRoutes({ server }); diff --git a/server/src/modules/server/user.routes.ts b/server/src/modules/server/user.routes.ts deleted file mode 100644 index 2907c6b..0000000 --- a/server/src/modules/server/user.routes.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { zRoutes } from "shared"; - -import { getUserFromRequest } from "../../security/authenticationService"; -import { generateApiKey } from "../actions/users.actions"; -import { Server } from "./server"; - -export const userRoutes = ({ server }: { server: Server }) => { - /** - * Génerer une clé API - */ - server.get( - "/user/generate-api-key", - { - schema: zRoutes.get["/user/generate-api-key"], - onRequest: [server.auth(zRoutes.get["/user/generate-api-key"])], - }, - async (request, response) => { - const user = getUserFromRequest(request, zRoutes.get["/user/generate-api-key"]); - const api_key = await generateApiKey(user); - return response.status(200).send({ api_key }); - } - ); -}; diff --git a/server/src/modules/server/utils/password.utils.ts b/server/src/modules/server/utils/password.utils.ts deleted file mode 100644 index 78bf9b7..0000000 --- a/server/src/modules/server/utils/password.utils.ts +++ /dev/null @@ -1,39 +0,0 @@ -import Boom from "@hapi/boom"; -import crypto from "crypto"; - -import config from "@/config"; - -export const generateSalt = () => { - return crypto.randomBytes(16).toString("hex"); -}; - -export const hashPassword = (password: crypto.BinaryLike, salt?: crypto.BinaryLike) => { - const iterations = config.auth.hashRounds; - const keylen = 64; - const digest = "sha512"; - - if (!salt) { - salt = generateSalt(); - } - - const hashedPassword = crypto.pbkdf2Sync(password, salt, iterations, keylen, digest); - - return `${hashedPassword.toString("hex")}$${iterations}$${salt}`; -}; - -export const verifyPassword = (password: crypto.BinaryLike, storedHash: string) => { - const [hashedStoredPassword, _iterations, salt] = storedHash.split("$"); - - if (!hashedStoredPassword) { - throw Boom.internal("verifyPassword: Invalid stored hash"); - } - - const hashedPasswordWithSalt = hashPassword(password, salt); - const [hashedPassword] = hashedPasswordWithSalt.split("$"); - - if (!hashedPassword) { - throw Boom.internal("verifyPassword: Invalid hashed password"); - } - - return crypto.timingSafeEqual(Buffer.from(hashedPassword), Buffer.from(hashedStoredPassword)); -}; diff --git a/server/src/security/accessTokenService.ts b/server/src/security/accessTokenService.ts deleted file mode 100644 index 8b0dbbb..0000000 --- a/server/src/security/accessTokenService.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { forbidden, internal } from "@hapi/boom"; -import { captureException } from "@sentry/node"; -import jwt from "jsonwebtoken"; -import { PathParam, QueryString } from "shared/helpers/generateUri"; -import { IUser } from "shared/models/user.model"; -import { IRouteSchema, ISecuredRouteSchema, WithSecurityScheme } from "shared/routes/common.routes"; -import { Jsonify } from "type-fest"; -import { AnyZodObject, z } from "zod"; - -import config from "@/config"; - -// cf https://www.sistrix.com/ask-sistrix/technical-seo/site-structure/url-length-how-long-can-a-url-be -const INTERNET_EXPLORER_V10_MAX_LENGTH = 2083; -const OUTLOOK_URL_MAX_LENGTH = 8192; -const NGINX_URL_MAX_LENGTH = 4096; -const URL_MAX_LENGTH = Math.min(INTERNET_EXPLORER_V10_MAX_LENGTH, OUTLOOK_URL_MAX_LENGTH, NGINX_URL_MAX_LENGTH); -const TOKEN_MAX_LENGTH = URL_MAX_LENGTH - config.publicUrl.length; - -export type SchemaWithSecurity = Pick & WithSecurityScheme; - -type IScope = { - path: S["path"]; - method: S["method"]; - options: - | "all" - | { - params: S["params"] extends AnyZodObject ? Partial>> : undefined; - querystring: S["querystring"] extends AnyZodObject ? Partial>> : undefined; - }; - resources: { - [key in keyof S["securityScheme"]["ressources"]]: ReadonlyArray; - }; -}; - -type IScopeParam = Pick, "options" | "resources"> & { - schema: S; -}; - -export const generateScope = (scope: IScopeParam): IScope => { - const { schema, options, resources } = scope; - - const requiredResources = Object.keys(schema.securityScheme.ressources); - const providedResources = new Set(Object.keys(resources)); - for (const requiredResource of requiredResources) { - if (!providedResources.has(requiredResource)) { - throw internal("generateScope: Missing resource", { scope, requiredResource }); - } - providedResources.delete(requiredResource); - } - - if (providedResources.size > 0) { - throw internal("generateScope: Extra resources", { scope, extraResources: providedResources }); - } - - return { options, resources, path: schema.path, method: schema.method }; -}; - -export type IAccessToken = { - identity: { - email: string; - }; - scopes: ReadonlyArray>; -}; - -export function generateAccessToken( - user: IUser | IAccessToken["identity"], - scopes: ReadonlyArray>, - options: { expiresIn?: string } = {} -): string { - const identity: IAccessToken["identity"] = { email: user.email.toLowerCase() }; - - const data: IAccessToken = { identity, scopes }; - - const token = jwt.sign(data, config.auth.user.jwtSecret, { - expiresIn: options.expiresIn ?? config.auth.user.expiresIn, - issuer: config.publicUrl, - }); - - if (token.length > TOKEN_MAX_LENGTH) { - captureException(internal(`Token généré trop long : ${token.length}`)); - } - return token; -} - -export function getAccessTokenScope( - token: IAccessToken | null, - schema: Pick, - params: PathParam | undefined, - querystring: QueryString | undefined -): IScope | null { - return ( - token?.scopes.find((s) => { - if (s.path !== schema.path || s.method !== schema.method) { - return false; - } - - if (s.options === "all") { - return true; - } - - if (s.options.params) { - const requiredParams = s.options.params; - for (const [key, requiredValue] of Object.entries(requiredParams)) { - if (params?.[key] !== requiredValue) { - return false; - } - } - } - - if (s.options.querystring) { - const requiredQuerystring = s.options.querystring; - for (const [key, value] of Object.entries(requiredQuerystring)) { - const requiredValues = Array.isArray(value) ? new Set(value) : new Set([value]); - const inputValues = querystring?.[key] ?? []; - - if (Array.isArray(inputValues)) { - for (const inputValue of inputValues) { - requiredValues.delete(inputValue); - } - } else { - requiredValues.delete(inputValues); - } - - if (requiredValues.size > 0) { - return false; - } - } - } - - return true; - }) ?? null - ); -} - -export function parseAccessToken( - accessToken: null | string, - schema: Pick, - params: PathParam | undefined, - querystring: QueryString | undefined -): IAccessToken | null { - if (!accessToken) { - return null; - } - - try { - const data = jwt.verify(accessToken, config.auth.user.jwtSecret, { - complete: true, - issuer: config.publicUrl, - }); - - const token = data.payload as IAccessToken; - - const scope = getAccessTokenScope(token, schema, params, querystring); - - if (!scope) { - throw forbidden("Scope does not match"); - } - - return token; - } catch (err) { - const error = forbidden("Invalid Access Token"); - error.cause = err; - throw error; - } -} diff --git a/server/src/security/authenticationService.ts b/server/src/security/authenticationService.ts deleted file mode 100644 index 7f10f68..0000000 --- a/server/src/security/authenticationService.ts +++ /dev/null @@ -1,152 +0,0 @@ -import Boom from "@hapi/boom"; -import { captureException } from "@sentry/node"; -import { FastifyRequest } from "fastify"; -import jwt, { JwtPayload } from "jsonwebtoken"; -import { ObjectId } from "mongodb"; -import { PathParam, QueryString } from "shared/helpers/generateUri"; -import { IUser } from "shared/models/user.model"; -import { ISecuredRouteSchema, WithSecurityScheme } from "shared/routes/common.routes"; -import { UserWithType } from "shared/security/permissions"; -import { assertUnreachable } from "shared/utils/assertUnreachable"; - -import config from "@/config"; - -import { compareKeys } from "../common/utils/cryptoUtils"; -import { decodeToken } from "../common/utils/jwtUtils"; -import { getDbCollection } from "../common/utils/mongodbUtils"; -import { getSession } from "../modules/actions/sessions.actions"; -import { updateUser } from "../modules/actions/users.actions"; -import { IAccessToken, parseAccessToken } from "./accessTokenService"; - -export type IUserWithType = UserWithType<"token", IAccessToken> | UserWithType<"user", IUser>; - -declare module "fastify" { - interface FastifyRequest { - user?: null | IUserWithType; - } -} - -type AuthenticatedUser = - AuthScheme extends "access-token" - ? UserWithType<"token", IAccessToken> - : AuthScheme extends "api-key" | "cookie-session" - ? UserWithType<"user", IUser> - : never; - -export const getUserFromRequest = ( - req: Pick, - _schema: S -): AuthenticatedUser["value"] => { - if (!req.user) { - throw Boom.internal("User should be authenticated"); - } - - return req.user.value as AuthenticatedUser["value"]; -}; - -async function authCookieSession(req: FastifyRequest): Promise | null> { - const token = req.cookies?.[config.session.cookieName]; - - if (!token) { - throw Boom.forbidden("Session invalide"); - } - - try { - const session = await getSession({ token }); - - if (!session) { - return null; - } - - const { email } = jwt.verify(token, config.auth.user.jwtSecret) as JwtPayload; - - const user = await getDbCollection("users").findOne({ email: email.toLowerCase() }); - - return user ? { type: "user", value: user } : user; - } catch (error) { - captureException(error); - return null; - } -} - -async function authApiKey(req: FastifyRequest): Promise | null> { - const token = extractBearerTokenFromHeader(req); - - if (!token) { - throw Boom.forbidden("Jeton manquant"); - } - - try { - const { _id, api_key } = decodeToken(token) as JwtPayload; - - const user = await getDbCollection("users").findOne({ _id: new ObjectId(_id) }); - - if (!user || !user?.api_key || !compareKeys(user.api_key, api_key)) { - throw Boom.forbidden("Jeton invalide"); - } - - const api_key_used_at = new Date(); - - await updateUser(user.email, { api_key_used_at }); - return user ? { type: "user", value: { ...user, api_key_used_at } } : null; - } catch (error) { - throw Boom.forbidden("Jeton invalide"); - } -} - -const bearerRegex = /^bearer\s+(\S+)$/i; -function extractBearerTokenFromHeader(req: FastifyRequest): null | string { - const { authorization } = req.headers; - - if (!authorization) { - return null; - } - - const matches = authorization.match(bearerRegex); - - return matches === null ? null : matches[1]; -} - -async function authAccessToken( - req: FastifyRequest, - schema: S -): Promise | null> { - const token = parseAccessToken( - extractBearerTokenFromHeader(req), - schema, - req.params as PathParam, - req.query as QueryString - ); - - if (token === null) { - return null; - } - - return token ? { type: "token", value: token } : null; -} - -export async function authenticationMiddleware(schema: S, req: FastifyRequest) { - if (!schema.securityScheme) { - throw Boom.internal("Missing securityScheme"); - } - - const securityScheme = schema.securityScheme; - - switch (securityScheme.auth) { - case "cookie-session": - req.user = await authCookieSession(req); - break; - case "api-key": - req.user = await authApiKey(req); - break; - case "access-token": - req.user = await authAccessToken(req, schema); - break; - default: - assertUnreachable(securityScheme.auth); - } - - if (!req.user) { - throw Boom.unauthorized(); - } -} diff --git a/server/src/security/authorisationService.ts b/server/src/security/authorisationService.ts deleted file mode 100644 index d09c3bc..0000000 --- a/server/src/security/authorisationService.ts +++ /dev/null @@ -1,153 +0,0 @@ -import Boom from "@hapi/boom"; -import { FastifyRequest } from "fastify"; -import { ObjectId } from "mongodb"; -import { PathParam, QueryString } from "shared/helpers/generateUri"; -import { IUser } from "shared/models/user.model"; -import { IRouteSchema, WithSecurityScheme } from "shared/routes/common.routes"; -import { AccessPermission, AccessResourcePath, AdminRole, NoneRole, Role } from "shared/security/permissions"; -import { assertUnreachable } from "shared/utils/assertUnreachable"; -import { Primitive } from "zod"; -import { zObjectId } from "zod-mongodb-schema"; - -import { getDbCollection } from "../common/utils/mongodbUtils"; -import { getAccessTokenScope, IAccessToken, SchemaWithSecurity } from "./accessTokenService"; -import { getUserFromRequest } from "./authenticationService"; - -export type Ressources = { - users: Array; -}; - -// Specify what we need to simplify mocking in tests -type IRequest = Pick; - -function getAccessResourcePathValue(path: AccessResourcePath, req: IRequest) { - const obj = req[path.type] as Record; - return obj[path.key]; -} - -async function getUserResource(schema: S, req: IRequest): Promise { - if (!schema.securityScheme.ressources.user) { - return []; - } - - return ( - await Promise.all( - schema.securityScheme.ressources.user.map(async (userDef) => { - if ("_id" in userDef) { - const userOpt = await getDbCollection("users").findOne({ - _id: zObjectId.parse(getAccessResourcePathValue(userDef._id, req)), - }); - - return userOpt ? [userOpt] : []; - } - - assertUnreachable(userDef); - }) - ) - ).flatMap((_) => _); -} - -export async function getResources(schema: S, req: IRequest): Promise { - const [users] = await Promise.all([getUserResource(schema, req)]); - - return { - users, - }; -} - -function getUserRole(userOrToken: IAccessToken | IUser): Role { - if ("identity" in userOrToken) { - return NoneRole; - } - - return userOrToken.is_admin ? AdminRole : NoneRole; -} - -function canAccessUser(user: IUser, resource: Ressources["users"][number]): boolean { - return user.is_admin || resource._id.toString() === user._id.toString(); -} - -export function isAuthorizedUser(access: AccessPermission, user: IUser, resources: Ressources): boolean { - if (!getUserRole(user).permissions.includes(access)) { - return false; - } - - switch (access) { - case "user:manage": - return resources.users.every((r) => canAccessUser(user, r)); - case "admin": - return user.is_admin; - default: - assertUnreachable(access); - } -} - -function canAccessRessource( - allowedIds: ReadonlyArray | undefined, - requiredResources: Array<{ _id: ObjectId }> -) { - const set: Set = new Set(allowedIds); - - for (const resource of requiredResources) { - if (!set.has(resource._id.toString())) { - return false; - } - } - - return true; -} - -export function isAuthorizedToken( - token: IAccessToken, - resources: Ressources, - schema: Pick, - params: PathParam | undefined, - querystring: QueryString | undefined -): boolean { - const scope = getAccessTokenScope(token, schema, params, querystring); - - const keys = Object.keys(resources) as Array; - for (const key of keys) { - switch (key) { - case "users": { - if (!canAccessRessource(scope?.resources.user, resources.users)) { - return false; - } - break; - } - default: - assertUnreachable(key); - } - } - - return true; -} - -export async function authorizationnMiddleware & WithSecurityScheme>( - schema: S, - req: IRequest -) { - if (!schema.securityScheme) { - throw Boom.internal(`authorizationnMiddleware: route doesn't have security scheme`, { - method: schema.method, - path: schema.path, - }); - } - - const userOrToken = getUserFromRequest(req, schema); - - if (schema.securityScheme.access === null) { - return; - } - - const resources = await getResources(schema, req); - - const isAuthorized = - "identity" in userOrToken - ? isAuthorizedToken(userOrToken, resources, schema, req.params as PathParam, req.query as QueryString) - : isAuthorizedUser(schema.securityScheme.access, userOrToken, resources); - - if (!isAuthorized) { - throw Boom.forbidden(); - } -} diff --git a/server/static/emails/common/footer.ejs b/server/static/emails/common/footer.ejs deleted file mode 100644 index 6104ba8..0000000 --- a/server/static/emails/common/footer.ejs +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Voir cet email dans votre navigateur - - - - Cet email a été envoyé à <%= template.to %> -
- Vous avez reçu cet email suite à une action sur le tableau de bord de l'apprentissage. -
- Pour vous désinscrire, - cliquez ici -
- <% if (actions.markAsOpened) { %> - - <% } %> -
-
-
diff --git a/server/static/emails/common/head.ejs b/server/static/emails/common/head.ejs deleted file mode 100644 index d958704..0000000 --- a/server/static/emails/common/head.ejs +++ /dev/null @@ -1,34 +0,0 @@ - - Tableau de bord de l'apprentissage - - .link-nostyle { color: inherit; } - .highlight { font-weight:600; } - .left { padding-right: 5px; } - .right { padding-left: 5px; } - .icon { vertical-align: middle } - - - - - - - diff --git a/server/static/emails/common/header.ejs b/server/static/emails/common/header.ejs deleted file mode 100644 index 4b2d640..0000000 --- a/server/static/emails/common/header.ejs +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/server/static/emails/common/signature.ejs b/server/static/emails/common/signature.ejs deleted file mode 100644 index 2b0b0ed..0000000 --- a/server/static/emails/common/signature.ejs +++ /dev/null @@ -1,9 +0,0 @@ - - Cordialement, -
- L'équipe du tableau de bord de l’apprentissage -

- - Mission interministérielle pour l'apprentissage et les trajectoires professionnelles - -
diff --git a/server/static/emails/reset_password.mjml.ejs b/server/static/emails/reset_password.mjml.ejs deleted file mode 100644 index b9c1b0b..0000000 --- a/server/static/emails/reset_password.mjml.ejs +++ /dev/null @@ -1,32 +0,0 @@ - - <%- include('./common/head.ejs'); %> - - - <%- include('./common/header.ejs'); %> - - - - Bonjour, - -
- Une demande de réinitialisation de mot de passe a été faite pour votre compte (<%= template.to %>). -

Si vous êtes à l'origine de cette demande,
- merci de cliquer sur le lien ci-dessous : -
-
- - - Lien de réinitialisation de mot de passe (valable 1h) - - - <%- include('./common/signature.ejs'); %> -
-
-
- <%- include('./common/footer.ejs'); %> -
-
diff --git a/server/tests/globalSetup.ts b/server/tests/globalSetup.ts deleted file mode 100644 index 4526610..0000000 --- a/server/tests/globalSetup.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { config } from "dotenv"; -import { MongoClient } from "mongodb"; - -export default async () => { - return async () => { - config({ path: "./server/.env.test" }); - - const client = new MongoClient(process.env.MONGODB_URI?.replace("VITEST_POOL_ID", "") ?? ""); - try { - if (process.env.CI) { - return; - } - - await client.connect(); - const dbs = await client.db().admin().listDatabases(); - await Promise.all( - dbs.databases.map((db) => { - if (db.name.startsWith("contrat-test-")) { - return client.db(db.name).dropDatabase(); - } - - return; - }) - ); - } catch (e) { - console.error(e); - } finally { - await client.close(); - } - }; -}; diff --git a/server/tests/integration/server.test.ts b/server/tests/integration/server.test.ts index ea76665..064e23c 100644 --- a/server/tests/integration/server.test.ts +++ b/server/tests/integration/server.test.ts @@ -2,10 +2,9 @@ import assert from "assert"; import fastify, { RouteOptions } from "fastify"; import { ZodTypeProvider } from "fastify-type-provider-zod"; import { zRoutes } from "shared/index"; -import { IRouteSchemaGet, IRouteSchemaWrite, SecurityScheme } from "shared/routes/common.routes"; +import { IRouteSchemaGet, IRouteSchemaWrite } from "shared/routes/common.routes"; import { describe, it } from "vitest"; -import { describeAuthMiddleware } from "../../src/modules/server/middlewares/authMiddleware"; import { bind } from "../../src/modules/server/server"; describe("server", () => { @@ -21,7 +20,7 @@ describe("server", () => { const seen = new Set(); for (const route of routes) { - const { routePath, schema, prefix, onRequest = [], preHandler = [] } = route; + const { routePath, schema, prefix } = route; if (prefix !== "/api") { continue; @@ -45,37 +44,6 @@ describe("server", () => { assert.equal(!!sharedSchema, true, `${method} ${routePath}: schema not define in shared`); assert.equal(schema, sharedSchema, `${method} ${routePath}: schema not match shared schema`); - const onRequestAuth = (Array.isArray(onRequest) ? onRequest : [onRequest]).reduce((acc, fn) => { - // @ts-expect-error - const s = describeAuthMiddleware(fn); - if (s) { - acc.push(s); - } - return acc; - }, [] as SecurityScheme[]); - const preHandlerAuth = (Array.isArray(preHandler) ? preHandler : [preHandler]).reduce((acc, fn) => { - // @ts-expect-error - const s = describeAuthMiddleware(fn); - if (s) { - acc.push(s); - } - return acc; - }, [] as SecurityScheme[]); - - const expectedAuth: { onRequestAuth: SecurityScheme[]; preHandlerAuth: SecurityScheme[] } = { - onRequestAuth: [], - preHandlerAuth: [], - }; - if (sharedSchema.securityScheme) { - expectedAuth.onRequestAuth.push(sharedSchema.securityScheme); - } - - assert.deepEqual( - { onRequestAuth, preHandlerAuth }, - expectedAuth, - `${method} ${routePath}: security not match shared schema` - ); - seen.add(`${method} ${routePath}`); } } diff --git a/server/tests/modules/jobs/db/schemaValidation.test.ts b/server/tests/modules/jobs/db/schemaValidation.test.ts deleted file mode 100644 index 79f9cf8..0000000 --- a/server/tests/modules/jobs/db/schemaValidation.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -import { getDatabase } from "../../../../src/common/utils/mongodbUtils"; -import { countInvalidDocuments, validateDocuments } from "../../../../src/modules/jobs/db/schemaValidation"; -import { useMongo } from "../../../utils/mongo.utils"; - -const mongo = useMongo(); - -beforeAll(async () => { - await mongo.beforeAll(); - await getDatabase().createCollection("shipping", { - validator: { - $jsonSchema: { - bsonType: "object", - title: "Shipping Country Validation", - properties: { - country: { - enum: ["France", "United Kingdom", "United States"], - description: "Must be either France, United Kingdom, or United States", - }, - }, - }, - }, - }); -}); - -beforeEach(async () => { - await mongo.beforeEach(); -}); - -afterAll(async () => { - await getDatabase().dropCollection("shipping"); - await mongo.afterAll(); -}); - -describe("countInvalidDocuments", () => { - it("should return invalid documents count", async () => { - await getDatabase() - .collection("shipping") - .insertMany( - [ - { - item: "sweater", - size: "medium", - country: "Germany", // Invalid - }, - { - item: "sweater", - size: "medium", - country: "France", // Valid - }, - { - item: "pants", - size: "medium", - country: "Japan", // Invalid - }, - ], - { - bypassDocumentValidation: true, - } - ); - - await expect(countInvalidDocuments("shipping")).resolves.toBe(2); - }); - - it("should return 0 when documents are valid", async () => { - await getDatabase() - .collection("shipping") - .insertMany( - [ - { - item: "sweater", - size: "medium", - country: "United States", - }, - { - item: "sweater", - size: "medium", - country: "France", - }, - { - item: "pants", - size: "medium", - country: "United Kingdom", - }, - ], - { - bypassDocumentValidation: true, - } - ); - - await expect(countInvalidDocuments("shipping")).resolves.toBe(0); - }); -}); - -describe("validateDocuments", () => { - it("should reject when at least one document is invalid", async () => { - await getDatabase() - .collection("shipping") - .insertMany( - [ - { - item: "sweater", - size: "medium", - country: "Germany", // Invalid - }, - { - item: "sweater", - size: "medium", - country: "France", // Valid - }, - { - item: "pants", - size: "medium", - country: "Japan", // Invalid - }, - ], - { - bypassDocumentValidation: true, - } - ); - - await expect(validateDocuments("shipping")).rejects.toThrowError( - "Collection shipping contains 2 invalid documents" - ); - }); - - it("should resolves when all documents are valid", async () => { - await getDatabase() - .collection("shipping") - .insertMany( - [ - { - item: "sweater", - size: "medium", - country: "United States", - }, - { - item: "sweater", - size: "medium", - country: "France", - }, - { - item: "pants", - size: "medium", - country: "United Kingdom", - }, - ], - { - bypassDocumentValidation: true, - } - ); - - await expect(validateDocuments("shipping")).resolves.toBeUndefined(); - }); -}); diff --git a/server/tests/routes/auth.route.test.ts b/server/tests/routes/auth.route.test.ts deleted file mode 100644 index 21fb344..0000000 --- a/server/tests/routes/auth.route.test.ts +++ /dev/null @@ -1,222 +0,0 @@ -import assert from "node:assert"; - -import { afterAll, beforeAll, beforeEach, describe, it } from "vitest"; - -import config from "@/config"; -import { getSession } from "@/modules/actions/sessions.actions"; -import { createUser } from "@/modules/actions/users.actions"; -import createServer, { Server } from "@/modules/server/server"; - -import { useMongo } from "../utils/mongo.utils"; - -type Cookie = { - name: string; - value: string; - path: string; - httpOnly: boolean; -}; - -describe("Authentication", () => { - const mongo = useMongo(); - let app: Server; - - beforeAll(async () => { - app = await createServer(); - await Promise.all([app.ready(), mongo.beforeAll()]); - }, 15_000); - - beforeEach(async () => { - await mongo.beforeEach(); - }); - - afterAll(async () => { - await Promise.all([mongo.afterAll(), app.close()]); - }); - - it("should sign user in with valid credentials", async () => { - const user = await createUser({ - email: "email@exemple.fr", - password: "my-password", - is_admin: false, - }); - - const response = await app.inject({ - method: "POST", - url: "/api/auth/login", - payload: { - email: user?.email, - password: "my-password", - }, - }); - - assert.equal(response.statusCode, 200); - assert.equal(response.json()._id, user?._id); - assert.equal(response.json().email, user?.email); - assert.equal(response.json().password, undefined); - assert.equal(response.json().api_key, undefined); - }); - - it.skip("should not sign user in with invalid credentials", async () => { - const user = await createUser({ - email: "email@exemple.fr", - password: "my-password", - is_admin: false, - }); - - const responseIncorrectEmail = await app.inject({ - method: "POST", - url: "/api/auth/login", - payload: { - email: "another-email@exemple.fr", - password: "my-password", - }, - }); - - assert.equal(responseIncorrectEmail.statusCode, 403); - - const responseIncorrectPassword = await app.inject({ - method: "POST", - url: "/api/auth/login", - payload: { - email: user?.email, - password: "incorrect-password", - }, - }); - - assert.equal(responseIncorrectPassword.statusCode, 403); - }); - - it("should identify user and create session in db after signing in", async () => { - const user = await createUser({ - email: "email@exemple.fr", - password: "my-password", - is_admin: false, - }); - - const responseLogin = await app.inject({ - method: "POST", - url: "/api/auth/login", - payload: { - email: user?.email, - password: "my-password", - }, - }); - - const cookies = responseLogin.cookies as Cookie[]; - const sessionCookie = cookies.find((cookie) => cookie.name === config.session.cookieName) as Cookie; - - const session = await getSession({ token: sessionCookie.value }); - assert.equal(session?.token, sessionCookie.value); - - const response = await app.inject({ - method: "GET", - url: "/api/auth/session", - cookies: { - [sessionCookie.name]: sessionCookie.value, - }, - }); - - assert.equal(response.statusCode, 200); - assert.equal(response.json()._id, user?._id); - assert.equal(response.json().email, user?.email); - assert.equal(response.json().password, undefined); - assert.equal(response.json().api_key, undefined); - }); - - it("should not identify user using session and delete in database after signing out", async () => { - const user = await createUser({ - email: "email@example.fr", - password: "my-password", - is_admin: false, - }); - - const responseLogin = await app.inject({ - method: "POST", - url: "/api/auth/login", - payload: { - email: user?.email, - password: "my-password", - }, - }); - - let cookies = responseLogin.cookies as Cookie[]; - let sessionCookie = cookies.find((cookie) => cookie.name === config.session.cookieName) as Cookie; - - const responseLogout = await app.inject({ - method: "GET", - url: "/api/auth/logout", - cookies: { - [sessionCookie.name]: sessionCookie.value, - }, - }); - - cookies = responseLogout.cookies as Cookie[]; - sessionCookie = cookies.find((cookie) => cookie.name === config.session.cookieName) as Cookie; - - assert.equal(responseLogout.statusCode, 200); - assert.equal(sessionCookie.value, ""); - - const session = await getSession({ token: sessionCookie.value }); - assert.equal(session, null); - - const response = await app.inject({ - method: "GET", - url: "/api/auth/session", - cookies: { - [sessionCookie.name]: sessionCookie?.value as string, - }, - }); - - assert.equal(response.statusCode, 403); - }); - - // TODO SHOULD BE NOOP EMAIL - // it("should send reset password email", async () => { - // const user = await createUser({ - // email: "email@exemple.fr", - // password: "my-password", - // organisation_id: "64520f65d7726475fd54b3b7", - // }); - - // const response = await app.inject({ - // method: "GET", - // url: "/api/auth/reset-password", - // query: { - // email: user?.email as string, - // }, - // }); - - // assert.equal(response.statusCode, 200); - // }); - - // it("should reset user password", async () => { - // const user = await createUser({ - // email: "email@exemple.fr", - // password: "my-password", - // organisation_id: "64520f65d7726475fd54b3b7", - // }); - - // const token = createResetPasswordToken(user?.email as string); - // const newPassword = "new-password"; - // const response = await app.inject({ - // method: "POST", - // url: "/api/auth/reset-password", - // payload: { - // password: newPassword, - // token, - // }, - // }); - - // assert.equal(response.statusCode, 200); - - // const updatedPasswordUser = await findUser({ _id: user?._id }); - - // const match = verifyPassword( - // newPassword, - // updatedPasswordUser?.password as string - // ); - - // assert.notEqual(updatedPasswordUser?.password, user?.password); - // assert.equal(match, true); - // }); -}); diff --git a/server/tests/routes/users.route.test.ts b/server/tests/routes/users.route.test.ts deleted file mode 100644 index 95539e6..0000000 --- a/server/tests/routes/users.route.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import assert from "node:assert"; - -import { afterAll, beforeAll, beforeEach, describe, it } from "vitest"; - -import { createUserTokenSimple } from "../../src/common/utils/jwtUtils"; -import { getDbCollection } from "../../src/common/utils/mongodbUtils"; -import { createSession, createSessionToken } from "../../src/modules/actions/sessions.actions"; -import { createUser } from "../../src/modules/actions/users.actions"; -import createServer, { Server } from "../../src/modules/server/server"; -import { useMongo } from "../utils/mongo.utils"; - -describe("Users routes", () => { - const mongo = useMongo(); - let app: Server; - - beforeAll(async () => { - app = await createServer(); - await Promise.all([app.ready(), mongo.beforeAll()]); - }, 15_000); - - beforeEach(async () => { - await mongo.beforeEach(); - }); - - afterAll(async () => { - await Promise.all([mongo.afterAll(), app.close()]); - }); - - it("should get the current user with authorization token", async () => { - const user = await createUser({ - email: "connected@exemple.fr", - password: "my-password", - is_admin: false, - }); - - const token = createSessionToken(user.email); - await createSession({ token }); - - const userWithToken = await getDbCollection("users").findOne({ _id: user._id }); - - assert.equal(userWithToken?.api_key_used_at, undefined); - - const response = await app.inject({ - method: "GET", - url: "/api/auth/session", - headers: { - ["Cookie"]: `contrat_session=${token}`, - }, - }); - - assert.equal(response.statusCode, 200); - assert.equal(response.json()._id, user?._id); - assert.equal(response.json().email, "connected@exemple.fr"); - assert.equal(response.json().password, undefined); - assert.equal(response.json().api_key, undefined); - }); - - it("should allow admin to create a user", async () => { - const admin = await createUser({ - email: "admin@exemple.fr", - password: "my-password", - is_admin: true, - }); - - const token = createUserTokenSimple({ payload: { email: admin.email } }); - - await createSession({ - token, - }); - - const response = await app.inject({ - method: "POST", - url: "/api/admin/user", - payload: { - email: "email@exemple.fr", - password: "my-password", - is_admin: false, - }, - headers: { - ["Cookie"]: `contrat_session=${token}`, - }, - }); - - const user = await getDbCollection("users").findOne({ - email: "email@exemple.fr", - }); - - assert.equal(response.statusCode, 200); - assert.equal(response.json()._id, user?._id.toString()); - assert.equal(response.json().email, "email@exemple.fr"); - assert.equal(response.json().password, undefined); - }); - - it("should not allow non-admin to create a user", async () => { - const user = await createUser({ - email: "user@exemple.fr", - password: "my-password", - is_admin: false, - }); - - const token = createUserTokenSimple({ payload: { email: user.email } }); - - await createSession({ - token, - }); - - const response = await app.inject({ - method: "POST", - url: "/api/admin/user", - payload: { - email: "email@exemple.fr", - password: "my-password", - organisation_id: "64520f65d7726475fd54b3b7", - }, - headers: { - ["Cookie"]: `contrat_session=${token}`, - }, - }); - - assert.equal(response.statusCode, 403); - }); -}); diff --git a/server/tests/utils/mongo.utils.ts b/server/tests/utils/mongo.utils.ts deleted file mode 100644 index 61a94de..0000000 --- a/server/tests/utils/mongo.utils.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { modelDescriptors } from "shared/models/models"; - -import { - clearAllCollections, - closeMongodbConnection, - configureDbSchemaValidation, - connectToMongodb, - createIndexes, -} from "@/common/utils/mongodbUtils"; -import config from "@/config"; - -export const startAndConnectMongodb = async () => { - const workerId = `${process.env.VITEST_POOL_ID}-${process.env.VITEST_WORKER_ID}`; - - await connectToMongodb(config.mongodb.uri.replace("VITEST_POOL_ID", workerId)); - await Promise.all([createIndexes(), configureDbSchemaValidation(modelDescriptors)]); -}; - -export const stopMongodb = async () => { - await closeMongodbConnection(); -}; - -export const useMongo = () => { - return { - beforeAll: async () => { - await startAndConnectMongodb(); - }, - - afterAll: async () => { - await stopMongodb(); - }, - - beforeEach: async () => { - await clearAllCollections(); - }, - }; -}; diff --git a/server/tests/utils/security/accessTokenService.test.ts b/server/tests/utils/security/accessTokenService.test.ts deleted file mode 100644 index 576fa29..0000000 --- a/server/tests/utils/security/accessTokenService.test.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { ObjectId } from "mongodb"; -import { IUser } from "shared/models/user.model"; -import { zRoutes } from "shared/routes"; -import { describe, expect, it } from "vitest"; -import { z } from "zod"; -import { zObjectId } from "zod-mongodb-schema"; - -import { - generateAccessToken, - generateScope, - parseAccessToken, - SchemaWithSecurity, -} from "../../../src/security/accessTokenService"; - -const mockUser = (email: string): IUser => { - return { - _id: new ObjectId(), - email, - password: "", - is_admin: false, - api_key: null, - api_key_used_at: null, - updated_at: new Date(), - created_at: new Date(), - }; -}; -const ids = [new ObjectId().toString(), new ObjectId().toString(), new ObjectId().toString()]; - -describe("generateScope", () => { - it("should well-formed scope", () => { - const schema: SchemaWithSecurity = { - method: "get", - path: "/users/:id/:action", - params: z.object({ id: zObjectId, action: z.string() }).strict(), - querystring: z.object({ ids: z.array(zObjectId), q: z.string() }).strict(), - securityScheme: { - auth: "cookie-session", - access: "user:manage", - ressources: { - user: [{ _id: { type: "params", key: "id" } }, { _id: { type: "query", key: "ids" } }], - }, - }, - }; - - expect( - generateScope({ - schema, - options: "all", - resources: { user: ids }, - }) - ).toEqual({ - method: "get", - options: "all", - path: "/users/:id/:action", - resources: { - user: ids, - }, - }); - }); - - it("should throw when missing resource", () => { - const schema: SchemaWithSecurity = { - method: "get", - path: "/users/:id/:action", - params: z.object({ id: zObjectId, action: z.string() }).strict(), - querystring: z.object({ ids: z.array(zObjectId), q: z.string() }).strict(), - securityScheme: { - auth: "cookie-session", - access: "user:manage", - ressources: { - user: [{ _id: { type: "params", key: "id" } }, { _id: { type: "query", key: "ids" } }], - }, - }, - }; - - expect(() => - generateScope({ - schema, - options: "all", - resources: {}, - }) - ).toThrow("generateScope: Missing resource"); - expect(() => - generateScope({ - schema, - options: "all", - resources: { - user: [], - // @ts-expect-error - yop: [], - }, - }) - ).toThrow("generateScope: Extra resources"); - }); -}); - -describe("accessTokenService", () => { - const user = mockUser("self@mail.com"); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const schema: any = { - method: "get", - path: "/users/status/:id", - params: z.object({ id: zObjectId, action: z.string() }).strict(), - querystring: z.object({ ids: z.array(zObjectId), q: z.string() }).strict(), - securityScheme: { - auth: "cookie-session", - access: "user:manage", - ressources: { - user: [{ _id: { type: "params", key: "id" } }], - }, - }, - } satisfies SchemaWithSecurity; - - const options = { - params: { - id: ids[0].toString(), - }, - querystring: { - q: "hello", - }, - }; - - const expectTokenValid = (token: string) => - expect(parseAccessToken(token, schema, options.params, options.querystring)).toBeTruthy(); - const expectTokenInvalid = (token: string) => - expect(() => parseAccessToken(token, schema, options.params, options.querystring)).toThrow(); - - describe("valid tokens", () => { - it("should generate a token valid for a specific route", () => { - const token = generateAccessToken(user, [ - generateScope({ - schema, - options: "all", - resources: { user: ids }, - }), - ]); - expectTokenValid(token); - }); - it("should generate a token valid for a generic route", () => { - const token = generateAccessToken(user, [ - generateScope({ - schema, - resources: { user: ids }, - options: { - querystring: { q: "hello" }, - params: undefined, - }, - }), - ]); - expectTokenValid(token); - }); - }); - describe("invalid tokens", () => { - it("should detect an invalid token that has a different param", () => { - const token = generateAccessToken(user, [ - generateScope({ - schema, - resources: { user: ids }, - options: { - params: { - user: ids, - }, - querystring: { - q: "not allowed", - }, - }, - }), - ]); - expectTokenInvalid(token); - }); - it("should detect an invalid token that is for a different route", () => { - const token = generateAccessToken(user, [ - generateScope({ - schema: zRoutes.post["/admin/user"], - resources: {}, - options: "all", - }), - ]); - expectTokenInvalid(token); - }); - - it("should throw when missing/extra resource", () => { - expect(() => - generateScope({ - schema, - options: "all", - resources: {}, - }) - ).toThrow("generateScope: Missing resource"); - expect(() => - generateScope({ - schema, - options: "all", - resources: { - user: [], - recruiters: [], - }, - }) - ).toThrow("generateScope: Extra resources"); - }); - }); -}); diff --git a/server/tests/utils/security/authorisationService.test.ts b/server/tests/utils/security/authorisationService.test.ts deleted file mode 100644 index 8920c84..0000000 --- a/server/tests/utils/security/authorisationService.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { ObjectId } from "mongodb"; -import { IUser } from "shared/models/user.model"; -import { describe, expect, it } from "vitest"; -import { z } from "zod"; -import { zObjectId } from "zod-mongodb-schema"; - -import { - generateAccessToken, - generateScope, - parseAccessToken, - SchemaWithSecurity, -} from "../../../src/security/accessTokenService"; -import { isAuthorizedToken, isAuthorizedUser, Ressources } from "../../../src/security/authorisationService"; - -const mockUser = (email: string, data: Partial = {}): IUser => { - return { - _id: new ObjectId(), - email, - password: "", - is_admin: false, - api_key: null, - api_key_used_at: null, - updated_at: new Date(), - created_at: new Date(), - ...data, - }; -}; - -describe("isAuthorizedToken", () => { - const requiredUsers = [ - mockUser("required_1@mail.com"), - mockUser("required_2@mail.com"), - mockUser("required_3@mail.com"), - ]; - const otherUsers = [mockUser("extra_1@mail.com"), mockUser("extra_2@mail.com")]; - - const resources: Ressources = { - users: requiredUsers, - }; - - const schema: SchemaWithSecurity = { - method: "get", - path: "/users/:id/status", - params: z.object({ id: zObjectId }).strict(), - querystring: z.object({ ids: z.array(zObjectId) }).strict(), - securityScheme: { - auth: "cookie-session", - access: "user:manage", - ressources: { - user: [{ _id: { type: "params", key: "id" } }, { _id: { type: "query", key: "ids" } }], - }, - }, - }; - - it("should allow when all required ressources are allowed", () => { - const tokenString = generateAccessToken(otherUsers[0], [ - generateScope({ - schema, - resources: { - user: [...requiredUsers, ...otherUsers].map((user) => user._id.toString()), - }, - options: { - params: undefined, - querystring: undefined, - }, - }), - ]); - - const [first, ...rest] = requiredUsers; - const options = { - params: { id: first._id.toString() }, - querystring: { ids: rest.map((u) => u._id.toString()) }, - }; - const token = parseAccessToken(tokenString, schema, options.params, options.querystring); - if (!token) { - throw new Error("Unexpected"); - } - - expect(isAuthorizedToken(token, resources, schema, options.params, options.querystring)).toBe(true); - }); - - it("should denied when one required ressources from param is not allowed", () => { - const [first, ...rest] = requiredUsers; - - const tokenString = generateAccessToken(otherUsers[0], [ - generateScope({ - schema, - resources: { - user: rest.map((user) => user._id.toString()), - }, - options: { - params: undefined, - querystring: undefined, - }, - }), - ]); - - const options = { - params: { id: first._id.toString() }, - querystring: { ids: rest.map((u) => u._id.toString()) }, - }; - const token = parseAccessToken(tokenString, schema, options.params, options.querystring); - if (!token) { - throw new Error("Unexpected"); - } - - expect(isAuthorizedToken(token, resources, schema, options.params, options.querystring)).toBe(false); - }); - - it("should denied when one required ressources from questring is not allowed", () => { - const [first, ...rest] = requiredUsers; - - const tokenString = generateAccessToken(otherUsers[0], [ - generateScope({ - schema, - resources: { - user: [first, rest[0]].map((user) => user._id.toString()), - }, - options: { - params: undefined, - querystring: undefined, - }, - }), - ]); - - const options = { - params: { id: first._id.toString() }, - querystring: { ids: rest.map((u) => u._id.toString()) }, - }; - const token = parseAccessToken(tokenString, schema, options.params, options.querystring); - if (!token) { - throw new Error("Unexpected"); - } - - expect(isAuthorizedToken(token, resources, schema, options.params, options.querystring)).toBe(false); - }); -}); - -describe("isAuthorizedUser", () => { - const user1 = mockUser("user1@mail.com"); - const user2 = mockUser("user2@mail.com"); - const admin1 = mockUser("admin@mail.com", { is_admin: true }); - const admin2 = mockUser("admin@mail.com", { is_admin: true }); - - describe("admin permission", () => { - it("admin user should be allowed for any user", () => { - expect(isAuthorizedUser("user:manage", admin1, { users: [user1, user2, admin2] })).toBe(true); - }); - }); - - describe("user permission", () => { - it("basic user should be denied for any user (missing permission)", () => { - expect(isAuthorizedUser("user:manage", user1, { users: [user1] })).toBe(false); - }); - }); -}); diff --git a/server/tsup.config.ts b/server/tsup.config.ts index 34cc963..f3b24f4 100644 --- a/server/tsup.config.ts +++ b/server/tsup.config.ts @@ -1,25 +1,17 @@ -import fs from "node:fs"; -import { basename } from "node:path"; - import { defineConfig } from "tsup"; export default defineConfig((options) => { const isDev = options.env?.NODE_ENV !== "production"; const isWatched = options.env?.TSUP_WATCH === "true"; - const migrationFiles = fs.readdirSync("./src/db/migrations"); const entry: Record = { index: isDev ? "src/dev.ts" : "src/index.ts", }; - for (const file of migrationFiles) { - entry[`db/migrations/${basename(file, ".ts")}`] = `src/db/migrations/${file}`; - } - return { entry, watch: isWatched ? ["./src", "../shared"] : false, - onSuccess: isWatched ? "yarn cli start --withProcessor" : "", + onSuccess: isWatched ? "yarn cli start" : "", ignoreWatch: ["../shared/node_modules/**"], // In watch mode doesn't exit cleanly as it causes EADDRINUSE error killSignal: "SIGKILL", diff --git a/shared/helpers/mongoSchema/__snapshots__/mongoSchemaBuilder.test.ts.snap b/shared/helpers/mongoSchema/__snapshots__/mongoSchemaBuilder.test.ts.snap deleted file mode 100644 index d284c5f..0000000 --- a/shared/helpers/mongoSchema/__snapshots__/mongoSchemaBuilder.test.ts.snap +++ /dev/null @@ -1,238 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`zodToMongoSchema > should convert email_denied schema 1`] = ` -{ - "additionalProperties": false, - "bsonType": "object", - "properties": { - "_id": { - "bsonType": "objectId", - }, - "created_at": { - "bsonType": "date", - "description": "Date d'ajout en base de données", - }, - "email": { - "bsonType": "string", - "description": "L'email rejetée", - }, - "reason": { - "bsonType": "string", - "enum": [ - "unsubscribe", - ], - }, - "updated_at": { - "bsonType": "date", - "description": "Date de mise à jour en base de données", - }, - }, - "required": [ - "_id", - "email", - "reason", - "created_at", - ], -} -`; - -exports[`zodToMongoSchema > should convert email_events schema 1`] = ` -{ - "additionalProperties": false, - "bsonType": "object", - "properties": { - "_id": { - "bsonType": "objectId", - }, - "created_at": { - "bsonType": "date", - }, - "delivered_at": { - "anyOf": [ - { - "bsonType": "date", - }, - { - "bsonType": "null", - }, - ], - }, - "email": { - "bsonType": "string", - "description": "Addresse email", - }, - "errors": { - "bsonType": "array", - "items": { - "additionalProperties": false, - "bsonType": "object", - "properties": { - "message": { - "bsonType": "string", - }, - "type": { - "bsonType": "string", - "enum": [ - "fatal", - "soft_bounce", - "hard_bounce", - "complaint", - "invalid_email", - "blocked", - "error", - ], - }, - }, - }, - }, - "messageId": { - "bsonType": [ - "string", - "null", - ], - }, - "opened_at": { - "anyOf": [ - { - "bsonType": "date", - }, - { - "bsonType": "null", - }, - ], - }, - "template": { - "anyOf": [ - { - "additionalProperties": false, - "bsonType": "object", - "properties": { - "name": { - "bsonType": "string", - }, - "resetPasswordToken": { - "bsonType": "string", - }, - "to": { - "bsonType": "string", - }, - }, - "required": [ - "name", - "to", - "resetPasswordToken", - ], - }, - ], - }, - "updated_at": { - "bsonType": "date", - }, - }, - "required": [ - "_id", - "email", - "template", - "created_at", - "updated_at", - "opened_at", - "delivered_at", - "messageId", - "errors", - ], -} -`; - -exports[`zodToMongoSchema > should convert sessions schema 1`] = ` -{ - "additionalProperties": false, - "bsonType": "object", - "properties": { - "_id": { - "bsonType": "objectId", - }, - "created_at": { - "bsonType": "date", - "description": "Date d'ajout en base de données", - }, - "expires_at": { - "bsonType": "date", - "description": "Date d'expiration", - }, - "token": { - "bsonType": "string", - "description": "Token de la session", - }, - "updated_at": { - "bsonType": "date", - "description": "Date de mise à jour en base de données", - }, - }, - "required": [ - "_id", - "token", - "updated_at", - "created_at", - "expires_at", - ], -} -`; - -exports[`zodToMongoSchema > should convert users schema 1`] = ` -{ - "additionalProperties": false, - "bsonType": "object", - "properties": { - "_id": { - "bsonType": "objectId", - }, - "api_key": { - "bsonType": [ - "string", - "null", - ], - "description": "Clé API", - }, - "api_key_used_at": { - "anyOf": [ - { - "bsonType": "date", - }, - { - "bsonType": "null", - }, - ], - "description": "Date de dernière utilisation de la clé API", - }, - "created_at": { - "bsonType": "date", - "description": "Date d'ajout en base de données", - }, - "email": { - "bsonType": "string", - "description": "Email de l'utilisateur", - }, - "is_admin": { - "bsonType": "bool", - }, - "password": { - "bsonType": "string", - "description": "Mot de passe de l'utilisateur", - }, - "updated_at": { - "bsonType": "date", - "description": "Date de mise à jour en base de données", - }, - }, - "required": [ - "_id", - "email", - "password", - "is_admin", - "api_key", - "api_key_used_at", - "updated_at", - "created_at", - ], -} -`; diff --git a/shared/helpers/mongoSchema/mongoSchemaBuilder.test.ts b/shared/helpers/mongoSchema/mongoSchemaBuilder.test.ts deleted file mode 100644 index d70fb8d..0000000 --- a/shared/helpers/mongoSchema/mongoSchemaBuilder.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { zodToMongoSchema } from "zod-mongodb-schema"; - -import { modelDescriptors } from "../../models/models"; - -describe("zodToMongoSchema", () => { - modelDescriptors.forEach((descriptor) => { - it(`should convert ${descriptor.collectionName} schema`, () => { - expect(zodToMongoSchema(descriptor.zod)).toMatchSnapshot(); - }); - }); -}); diff --git a/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap b/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap deleted file mode 100644 index 72022a5..0000000 --- a/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap +++ /dev/null @@ -1,229 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`generateOpenApiSchema > should generate proper schema 1`] = ` -{ - "components": { - "parameters": {}, - "responses": { - "BadRequest": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "La requete ne respecte pas les reglès de validations.", - }, - "Forbidden": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "L'utilisateur n'a pas les droits d'effectuer l'opération demandée", - }, - "InternalServerError": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "Le serveur a rencontré une situation qu'il ne sait pas traiter.", - }, - "NotFound": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "Le serveur n'a pas trouvé la ressource demandée.", - }, - "ServiceUnavailable": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "Le serveur n'est pas prêt pour traiter la requête", - }, - "TooManyRequests": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "L'utilisateur a émis trop de requêtes dans un laps de temps donné.", - }, - "Unauthorized": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error", - }, - }, - }, - "description": "L'authentification est requise.", - }, - }, - "schemas": { - "Error": { - "additionalProperties": false, - "properties": { - "code": { - "type": [ - "string", - "null", - ], - }, - "data": { - "description": "Données contextuelles liées à l'erreur", - "example": { - "validationError": { - "code": "FST_ERR_VALIDATION", - "issues": [ - { - "code": "invalid_type", - "expected": "number", - "message": "Number attendu", - "path": [ - "longitude", - ], - "received": "nan", - }, - ], - "name": "ZodError", - "statusCode": 400, - "validationContext": "querystring", - }, - }, - }, - "message": { - "description": "Un message explicatif de l'erreur", - "example": "querystring.longitude: Number attendu", - "type": "string", - }, - "name": { - "description": "Le type générique de l'erreur", - "example": "Bad Request", - "type": "string", - }, - "statusCode": { - "description": "Le status code retourné", - "example": 400, - "type": "number", - }, - }, - "required": [ - "message", - "name", - "statusCode", - ], - "type": "object", - }, - }, - "securitySchemes": { - "api-key": { - "in": "header", - "name": "authorization", - "type": "apiKey", - }, - }, - }, - "info": { - "license": { - "name": "MIT", - }, - "title": "API documentation", - "version": "V1.0", - }, - "openapi": "3.1.0", - "paths": { - "/healthcheck": { - "get": { - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "additionalProperties": false, - "description": "API Health", - "properties": { - "env": { - "enum": [ - "local", - "recette", - "production", - "preview", - "test", - ], - "type": "string", - }, - "name": { - "example": "contrat", - "type": "string", - }, - "version": { - "example": "1.0.0", - "type": "string", - }, - }, - "required": [ - "name", - "version", - "env", - ], - "type": "object", - }, - }, - }, - "description": "API Health", - }, - "400": { - "$ref": "#/components/responses/BadRequest", - }, - "401": { - "$ref": "#/components/responses/Unauthorized", - }, - "403": { - "$ref": "#/components/responses/Forbidden", - }, - "404": { - "$ref": "#/components/responses/NotFound", - }, - "429": { - "$ref": "#/components/responses/TooManyRequests", - }, - "500": { - "$ref": "#/components/responses/InternalServerError", - }, - "503": { - "$ref": "#/components/responses/ServiceUnavailable", - }, - }, - "security": [], - "tags": [ - "système", - ], - }, - }, - }, - "servers": [ - { - "description": "Production", - "url": "https://contrat.apprentissage.beta.gouv.fr", - }, - ], - "webhooks": {}, -} -`; diff --git a/shared/helpers/openapi/generateOpenapi.test.ts b/shared/helpers/openapi/generateOpenapi.test.ts deleted file mode 100644 index b6c456e..0000000 --- a/shared/helpers/openapi/generateOpenapi.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { generateOpenApiSchema } from "./generateOpenapi"; - -describe("generateOpenApiSchema", () => { - it("should generate proper schema", async () => { - const s = generateOpenApiSchema("V1.0", "Production", "https://contrat.apprentissage.beta.gouv.fr"); - expect(s).toMatchSnapshot(); - }); -}); diff --git a/shared/helpers/openapi/generateOpenapi.ts b/shared/helpers/openapi/generateOpenapi.ts deleted file mode 100644 index 1052c63..0000000 --- a/shared/helpers/openapi/generateOpenapi.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { OpenApiGeneratorV31, OpenAPIRegistry, ResponseConfig, RouteConfig } from "@asteasolutions/zod-to-openapi"; -import { formatParamUrl } from "@fastify/swagger"; -import type { SecurityRequirementObject } from "openapi3-ts/oas30"; -import { ZodType } from "zod"; - -import { zRoutes } from "../../index"; -import { IRouteSchema, ZResError } from "../../routes/common.routes"; - -function generateOpenApiResponseObject(schema: ZodType, description: string | null = null): ResponseConfig { - return { - description: description ?? schema._def.openapi?.metadata?.description ?? schema.description ?? "", - content: { - "application/json": { - schema, - }, - }, - }; -} - -const commonResponses: { [statusCode: string]: ResponseConfig | { $ref: string } } = { - 400: { $ref: "#/components/responses/BadRequest" }, - 401: { $ref: "#/components/responses/Unauthorized" }, - 403: { $ref: "#/components/responses/Forbidden" }, - 404: { $ref: "#/components/responses/NotFound" }, - 429: { $ref: "#/components/responses/TooManyRequests" }, - 500: { $ref: "#/components/responses/InternalServerError" }, - 503: { $ref: "#/components/responses/ServiceUnavailable" }, -}; - -function registerResponseError(id: string, description: string, registry: OpenAPIRegistry) { - registry.registerComponent("responses", id, { - description, - content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } }, - }); -} - -function registerResponsesError(registry: OpenAPIRegistry) { - registry.register("Error", ZResError); - registerResponseError("BadRequest", "La requete ne respecte pas les reglès de validations.", registry); - registerResponseError("Unauthorized", "L'authentification est requise.", registry); - registerResponseError("Forbidden", "L'utilisateur n'a pas les droits d'effectuer l'opération demandée", registry); - registerResponseError("NotFound", "Le serveur n'a pas trouvé la ressource demandée.", registry); - registerResponseError( - "TooManyRequests", - "L'utilisateur a émis trop de requêtes dans un laps de temps donné.", - registry - ); - registerResponseError( - "InternalServerError", - "Le serveur a rencontré une situation qu'il ne sait pas traiter.", - registry - ); - registerResponseError("ServiceUnavailable", "Le serveur n'est pas prêt pour traiter la requête", registry); -} - -function generateOpenApiResponsesObject( - response: R -): { [statusCode: string]: ResponseConfig | { $ref: string } } { - const codes = Object.keys(response) as Array; - - return codes.reduce((acc, code: keyof R) => { - const schema: ZodType = response[code as `${1 | 2 | 3 | 4 | 5}${string}`]; - acc[code as string] = generateOpenApiResponseObject(code in acc ? schema.or(ZResError) : schema); - - return acc; - }, commonResponses); -} - -function generateOpenApiRequest(route: IRouteSchema): RouteConfig["request"] { - const requestParams: RouteConfig["request"] = {}; - - if (route.method !== "get" && route.body) { - requestParams.body = { - content: { - "application/json": { schema: route.body }, - }, - required: true, - }; - } - if (route.params) { - requestParams.params = route.params; - } - if (route.querystring) { - requestParams.query = route.querystring; - } - if (route.headers) { - requestParams.headers = route.headers; - } - - return requestParams; -} - -function getSecurityRequirementObject(route: IRouteSchema): SecurityRequirementObject[] { - if (route.securityScheme === null) { - return []; - } - - if (route.securityScheme.auth !== "api-key") { - throw new Error("getSecurityRequirementObject: securityScheme not supported"); - } - - return [{ "api-key": [] }]; -} - -function addOpenApiOperation( - path: string, - method: "get" | "put" | "post" | "delete", - route: IRouteSchema, - registry: OpenAPIRegistry -) { - if (!route.openapi) { - return; - } - - registry.registerPath({ - ...route.openapi, - method, - path: formatParamUrl(path), - request: generateOpenApiRequest(route), - // @ts-expect-error - responses: generateOpenApiResponsesObject(route.response), - security: getSecurityRequirementObject(route), - }); -} - -export function generateOpenApiSchema(version: string, env: string, publicUrl: string) { - const registry = new OpenAPIRegistry(); - - registry.registerComponent("securitySchemes", "api-key", { - type: "apiKey", - name: "authorization", - in: "header", - }); - registerResponsesError(registry); - - for (const [method, pathRoutes] of Object.entries(zRoutes)) { - for (const [path, route] of Object.entries(pathRoutes)) { - addOpenApiOperation(path, method as "get" | "put" | "post" | "delete", route, registry); - } - } - - const generator = new OpenApiGeneratorV31(registry.definitions); - - return generator.generateDocument({ - info: { - title: "API documentation", - version, - license: { - name: "MIT", - }, - }, - openapi: "3.1.0", - servers: [ - { - url: publicUrl, - description: env, - }, - ], - }); -} diff --git a/shared/helpers/zodWithOpenApi.ts b/shared/helpers/zodWithOpenApi.ts deleted file mode 100644 index 1d4e4f1..0000000 --- a/shared/helpers/zodWithOpenApi.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi"; -import { z } from "zod"; - -extendZodWithOpenApi(z); - -export { z }; diff --git a/shared/models/common.ts b/shared/models/common.ts deleted file mode 100644 index 294b75f..0000000 --- a/shared/models/common.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { CreateIndexesOptions, IndexSpecification } from "mongodb"; -import { ZodType } from "zod"; - -export type CollectionName = "email_denied" | "email_events" | "sessions" | "users"; - -export interface IModelDescriptor { - zod: ZodType; - indexes: [IndexSpecification, CreateIndexesOptions][]; - collectionName: CollectionName; -} - -export { zObjectId } from "zod-mongodb-schema"; diff --git a/shared/models/email_denied.model.ts b/shared/models/email_denied.model.ts deleted file mode 100644 index ad25fce..0000000 --- a/shared/models/email_denied.model.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { z } from "zod"; - -import { IModelDescriptor, zObjectId } from "./common"; - -const collectionName = "email_denied" as const; - -const indexes: IModelDescriptor["indexes"] = [[{ email: 1 }, {}]]; - -export const ZEmailDenied = z - .object({ - _id: zObjectId, - email: z.string().describe("L'email rejetée"), - reason: z.enum(["unsubscribe"]), - updated_at: z.date().optional().describe("Date de mise à jour en base de données"), - created_at: z.date().describe("Date d'ajout en base de données"), - }) - .strict(); - -export type IEmailDenied = z.output; - -export default { - zod: ZEmailDenied, - indexes, - collectionName, -}; diff --git a/shared/models/email_event.model.ts b/shared/models/email_event.model.ts deleted file mode 100644 index cc18c4e..0000000 --- a/shared/models/email_event.model.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Jsonify } from "type-fest"; -import { z } from "zod"; - -import { IModelDescriptor, zObjectId } from "./common"; -import { zTemplate } from "./email_event/email_templates"; - -const collectionName = "email_events" as const; - -const indexes: IModelDescriptor["indexes"] = [[{ type: 1, messageId: 1 }, {}]]; - -const zEmailError = z - .object({ - type: z.enum(["fatal", "soft_bounce", "hard_bounce", "complaint", "invalid_email", "blocked", "error"]).optional(), - message: z.string().optional(), - }) - .strict(); - -export type IEmailError = z.output; - -export const ZEmailEvent = z - .object({ - _id: zObjectId, - email: z.string().describe("Addresse email"), - template: zTemplate, - created_at: z.date(), - updated_at: z.date(), - opened_at: z.date().nullable(), - delivered_at: z.date().nullable(), - messageId: z.string().nullable(), - errors: z.array(zEmailError), - }) - .strict(); - -export type IEmailEvent = z.output; -export type IEventJsonJson = Jsonify>; - -export default { - zod: ZEmailEvent, - indexes, - collectionName, -}; diff --git a/shared/models/email_event/email_templates.ts b/shared/models/email_event/email_templates.ts deleted file mode 100644 index 9f89469..0000000 --- a/shared/models/email_event/email_templates.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Pour chaque template, déclarer les champs qui sont utilisés dans le template -// token: string; // obligatoire et commun à tous les emails, ajouté automatiquement dans l'emails.actions - -import { z } from "zod"; - -// Ignore any extra props added by jwt parsing (iat, iss, ...) -// eslint-disable-next-line zod/require-strict -const zTemplateResetPassword = z.object({ - name: z.literal("reset_password"), - to: z.string().email(), - resetPasswordToken: z.string(), -}); - -type ITemplateResetPassword = z.output; - -export const zTemplate = z.discriminatedUnion("name", [zTemplateResetPassword]); - -export type ITemplate = z.output; - -export type TemplatePayloads = { - reset_password: ITemplateResetPassword; -}; -export type TemplateName = keyof TemplatePayloads; diff --git a/shared/models/models.ts b/shared/models/models.ts deleted file mode 100644 index 8ac2e45..0000000 --- a/shared/models/models.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { IModelDescriptor } from "./common"; -import emailDeniedModelDescriptor, { IEmailDenied } from "./email_denied.model"; -import emailEventsModelDescriptor, { IEmailEvent } from "./email_event.model"; -import sessionsModelDescriptor, { ISession } from "./session.model"; -import usersModelDescriptor, { IUser } from "./user.model"; - -export const modelDescriptors: IModelDescriptor[] = [ - usersModelDescriptor, - sessionsModelDescriptor, - emailDeniedModelDescriptor, - emailEventsModelDescriptor, -]; - -export type IDocumentMap = { - email_denied: IEmailDenied; - email_events: IEmailEvent; - users: IUser; - sessions: ISession; -}; diff --git a/shared/models/session.model.ts b/shared/models/session.model.ts deleted file mode 100644 index 93953b4..0000000 --- a/shared/models/session.model.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Jsonify } from "type-fest"; -import { z } from "zod"; - -import { IModelDescriptor, zObjectId } from "./common"; - -const collectionName = "sessions" as const; - -const indexes: IModelDescriptor["indexes"] = [[{ expires_at: 1 }, { expireAfterSeconds: 0 }]]; - -export const ZSession = z - .object({ - _id: zObjectId, - token: z.string().describe("Token de la session"), - updated_at: z.date().describe("Date de mise à jour en base de données"), - created_at: z.date().describe("Date d'ajout en base de données"), - expires_at: z.date().describe("Date d'expiration"), - }) - .strict(); - -export type ISession = z.output; -export type ISessionJson = Jsonify>; - -export default { - zod: ZSession, - indexes, - collectionName, -}; diff --git a/shared/models/user.model.ts b/shared/models/user.model.ts deleted file mode 100644 index a057d60..0000000 --- a/shared/models/user.model.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Jsonify } from "type-fest"; -import { z } from "zod"; - -import { IModelDescriptor, zObjectId } from "./common"; - -const collectionName = "users" as const; - -const indexes: IModelDescriptor["indexes"] = [ - [{ email: 1 }, { unique: true }], - [ - { - email: "text", - }, - { - name: "email_text", - default_language: "french", - collation: { - locale: "simple", - strength: 1, - }, - }, - ], - [ - { - email: "text", - }, - { - weights: { - email: 10, - }, - name: "search", - }, - ], -]; - -export const zUser = z - .object({ - _id: zObjectId, - email: z.string().email().describe("Email de l'utilisateur"), - password: z.string().describe("Mot de passe de l'utilisateur"), - is_admin: z.boolean(), - api_key: z.string().nullable().describe("Clé API"), - api_key_used_at: z.date().nullable().describe("Date de dernière utilisation de la clé API"), - updated_at: z.date().describe("Date de mise à jour en base de données"), - created_at: z.date().describe("Date d'ajout en base de données"), - }) - .strict(); - -export const zUserCreate = zUser - .pick({ - email: true, - password: true, - is_admin: true, - }) - .strict(); - -export const zUserPublic = z - .object({ - _id: zObjectId, - email: zUser.shape.email, - is_admin: zUser.shape.is_admin, - has_api_key: z.boolean(), - api_key_used_at: zUser.shape.api_key_used_at, - updated_at: zUser.shape.updated_at, - created_at: zUser.shape.created_at, - }) - .strict(); - -export type IUser = z.output; -export type IUserPublic = Jsonify>; -export type IUserCreate = Jsonify>; - -export function toPublicUser(user: IUser): z.output { - return zUserPublic.parse({ - _id: user._id, - email: user.email, - is_admin: user.is_admin, - has_api_key: Boolean(user.api_key), - api_key_used_at: user.api_key_used_at, - updated_at: user.updated_at, - created_at: user.created_at, - }); -} - -export default { - zod: zUser, - indexes, - collectionName, -}; diff --git a/shared/package.json b/shared/package.json index 9773cf6..ecf46ef 100644 --- a/shared/package.json +++ b/shared/package.json @@ -15,18 +15,13 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@asteasolutions/zod-to-openapi": "^6.2.0", "lodash-es": "^4.17.21", - "luhn": "^2.4.1", - "openapi3-ts": "^4.1.2", "react": "18.2.0", "type-fest": "^4.2.0", - "zod": "^3.22.1", - "zod-to-json-schema": "3.21.4" + "zod": "^3.22.1" }, "devDependencies": { "bson": "^5.4.0", - "mongodb": "^5.7.0", "typescript": "^5.1.6", "zod": "^3.22.1" } diff --git a/shared/routes/admin/admin.routes.ts b/shared/routes/admin/admin.routes.ts deleted file mode 100644 index 551233e..0000000 --- a/shared/routes/admin/admin.routes.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { z } from "zod"; - -import { zObjectId } from "../../models/common"; -import { zUserCreate, zUserPublic } from "../../models/user.model"; -import { IRoutesDef, ZReqParamsSearchPagination } from "../common.routes"; - -export const zUserAdminRoutes = { - get: { - "/admin/users": { - method: "get", - path: "/admin/users", - querystring: ZReqParamsSearchPagination, - response: { "200": z.array(zUserPublic) }, - securityScheme: { - auth: "cookie-session", - access: "admin", - ressources: {}, - }, - }, - "/admin/users/:id": { - method: "get", - path: "/admin/users/:id", - params: z.object({ id: zObjectId }).strict(), - response: { "200": zUserPublic }, - securityScheme: { - auth: "cookie-session", - access: "admin", - ressources: {}, - }, - }, - }, - post: { - "/admin/user": { - method: "post", - path: "/admin/user", - body: zUserCreate, - response: { - "200": zUserPublic, - }, - securityScheme: { - auth: "cookie-session", - access: "admin", - ressources: {}, - }, - }, - }, -} as const satisfies IRoutesDef; diff --git a/shared/routes/auth.routes.ts b/shared/routes/auth.routes.ts deleted file mode 100644 index da2f83f..0000000 --- a/shared/routes/auth.routes.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { z } from "zod"; - -import { zUser, zUserPublic } from "../models/user.model"; -import { IRoutesDef, ZReqHeadersAuthorization, ZResOk } from "./common.routes"; - -export const zAuthRoutes = { - get: { - "/auth/reset-password": { - method: "get", - path: "/auth/reset-password", - querystring: z.object({ email: z.string().email() }).strict(), - response: { - "200": ZResOk, - }, - securityScheme: null, - }, - "/auth/logout": { - method: "get", - path: "/auth/logout", - response: { - "200": ZResOk, - }, - securityScheme: null, - }, - "/auth/session": { - method: "get", - path: "/auth/session", - response: { - "200": zUserPublic, - }, - headers: ZReqHeadersAuthorization, - securityScheme: { - auth: "cookie-session", - access: null, - ressources: {}, - }, - }, - }, - post: { - "/auth/reset-password": { - method: "post", - path: "/auth/reset-password", - body: z - .object({ - password: zUser.shape.password, - }) - .strict(), - response: { - "200": ZResOk, - }, - securityScheme: { - auth: "access-token", - access: null, - ressources: {}, - }, - }, - "/auth/login": { - method: "post", - path: "/auth/login", - body: z - .object({ - email: zUser.shape.email, - password: zUser.shape.password, - }) - .strict(), - response: { - "200": zUserPublic, - }, - securityScheme: null, - }, - }, -} as const satisfies IRoutesDef; - -export interface IStatus { - error?: boolean; - message?: string; -} diff --git a/shared/routes/cerfa.routes.ts b/shared/routes/cerfa.routes.ts index 4df4478..c81d827 100644 --- a/shared/routes/cerfa.routes.ts +++ b/shared/routes/cerfa.routes.ts @@ -23,7 +23,6 @@ export const zCerfaRoutes = { response: { "2xx": z.any(), }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/common.routes.ts b/shared/routes/common.routes.ts index bff8be5..fcb436b 100644 --- a/shared/routes/common.routes.ts +++ b/shared/routes/common.routes.ts @@ -1,48 +1,13 @@ -import { oas31 } from "openapi3-ts"; import { Jsonify } from "type-fest"; -import { AnyZodObject, ZodType } from "zod"; - -import { z } from "../helpers/zodWithOpenApi"; -import { AccessPermission, AccessRessouces } from "../security/permissions"; +import { AnyZodObject, z, ZodType } from "zod"; export const ZResError = z .object({ - data: z - .any() - .optional() - .openapi({ - description: "Données contextuelles liées à l'erreur", - example: { - validationError: { - issues: [ - { - code: "invalid_type", - expected: "number", - received: "nan", - path: ["longitude"], - message: "Number attendu", - }, - ], - name: "ZodError", - statusCode: 400, - code: "FST_ERR_VALIDATION", - validationContext: "querystring", - }, - }, - }), + data: z.any().optional(), code: z.string().nullish(), - message: z.string().openapi({ - description: "Un message explicatif de l'erreur", - example: "querystring.longitude: Number attendu", - }), - name: z.string().openapi({ - description: "Le type générique de l'erreur", - example: "Bad Request", - }), - statusCode: z.number().openapi({ - description: "Le status code retourné", - example: 400, - }), + message: z.string(), + name: z.string(), + statusCode: z.number(), }) .strict(); @@ -68,28 +33,12 @@ export const ZReqHeadersAuthorization = z export type AuthStrategy = "api-key" | "cookie-session" | "access-token"; -export type SecuritySchemeWithAcl = { - auth: AuthStrategy; - access: AccessPermission; - ressources: AccessRessouces; -}; - -export type SecuritySchemeNoAcl = { - auth: AuthStrategy; - access: null; - ressources: Record; -}; - -export type SecurityScheme = SecuritySchemeWithAcl | SecuritySchemeNoAcl; - interface IRouteSchemaCommon { path: string; querystring?: AnyZodObject; headers?: AnyZodObject; params?: AnyZodObject; response: { [statuscode: `${1 | 2 | 3 | 4 | 5}${string}`]: ZodType }; - openapi?: null | Omit; - securityScheme: SecurityScheme | null; } export interface IRouteSchemaGet extends IRouteSchemaCommon { @@ -101,12 +50,7 @@ export interface IRouteSchemaWrite extends IRouteSchemaCommon { body?: ZodType; } -export type WithSecurityScheme = { - securityScheme: SecurityScheme; -}; - export type IRouteSchema = IRouteSchemaGet | IRouteSchemaWrite; -export type ISecuredRouteSchema = IRouteSchema & WithSecurityScheme; export type IRoutesDef = { get?: Record; diff --git a/shared/routes/controls.routes.ts b/shared/routes/controls.routes.ts index 8a6776f..7e5ce1a 100644 --- a/shared/routes/controls.routes.ts +++ b/shared/routes/controls.routes.ts @@ -19,7 +19,6 @@ export const zControlsRoutes = { }) .strict(), }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/core.routes.ts b/shared/routes/core.routes.ts index 287d7d7..8d67cc3 100644 --- a/shared/routes/core.routes.ts +++ b/shared/routes/core.routes.ts @@ -1,4 +1,5 @@ -import { z } from "../helpers/zodWithOpenApi"; +import { z } from "zod"; + import { IRoutesDef } from "./common.routes"; export const zCoreRoutes = { @@ -9,29 +10,13 @@ export const zCoreRoutes = { response: { "200": z .object({ - name: z.string().openapi({ - example: "contrat", - }), - version: z.string().openapi({ - example: "1.0.0", - }), - env: z.enum(["local", "recette", "production", "preview", "test"]), + name: z.string(), + version: z.string(), + env: z.enum(["local", "recette", "production", "test"]), }) .describe("API Health") .strict(), }, - securityScheme: null, - openapi: { - tags: ["système"] as string[], - }, - }, - "/healthcheck/sentry": { - method: "get", - path: "/healthcheck/sentry", - response: { - "200": z.never(), - }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/emails.routes.ts b/shared/routes/emails.routes.ts deleted file mode 100644 index 1521c9a..0000000 --- a/shared/routes/emails.routes.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { z } from "zod"; - -import { zObjectId } from "../models/common"; -import { IRoutesDef } from "./common.routes"; - -export const zEmailRoutes = { - get: { - "/emails/preview": { - method: "get", - path: "/emails/preview", - querystring: z - .object({ - data: z.string(), - }) - .strict(), - response: { - "200": z.unknown(), - }, - securityScheme: null, - }, - "/emails/:id/markAsOpened": { - method: "get", - path: "/emails/:id/markAsOpened", - params: z.object({ id: zObjectId }).strict(), - response: { - "200": z.unknown(), - }, - securityScheme: { - auth: "access-token", - access: null, - ressources: {}, - }, - }, - "/emails/unsubscribe": { - method: "get", - path: "/emails/unsubscribe", - querystring: z - .object({ - data: z.string(), - }) - .strict(), - response: { - "200": z.unknown(), - }, - securityScheme: null, - }, - }, - post: { - "/emails/webhook": { - method: "post", - path: "/emails/webhook", - querystring: z - .object({ - webhookKey: z.string(), - }) - .passthrough(), - body: z - .object({ - event: z.string(), //https://developers.sendinblue.com/docs/transactional-webhooks - "message-id": z.string(), - }) - .strict(), - response: { - "200": z.unknown(), - }, - securityScheme: null, - }, - }, -} as const satisfies IRoutesDef; diff --git a/shared/routes/geo.routes.ts b/shared/routes/geo.routes.ts index d202bb4..4b0bd97 100644 --- a/shared/routes/geo.routes.ts +++ b/shared/routes/geo.routes.ts @@ -15,7 +15,6 @@ export const zGeoRoutes = { response: { "2xx": z.any(), }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/index.test.ts b/shared/routes/index.test.ts index 24e6666..7de9619 100644 --- a/shared/routes/index.test.ts +++ b/shared/routes/index.test.ts @@ -3,7 +3,7 @@ import assert from "node:assert"; import { describe, it } from "vitest"; import { zRoutes } from "."; -import { IRouteSchema, IRouteSchemaGet, IRouteSchemaWrite, IRoutesDef, ZResError } from "./common.routes"; +import { IRouteSchema, ZResError } from "./common.routes"; describe("zRoutes", () => { it("should define error schema compatible with default one from error middleware", () => { @@ -36,26 +36,4 @@ describe("zRoutes", () => { } } }); - - it("should access ressources be defined correctly", () => { - for (const [method, zMethodRoutes] of Object.entries(zRoutes as IRoutesDef)) { - for (const [path, def] of Object.entries(zMethodRoutes)) { - const typedDef = def as IRouteSchemaWrite | IRouteSchemaGet; - if (typedDef.securityScheme) { - for (const [resourceType, resourceAccesses] of Object.entries(typedDef.securityScheme.ressources)) { - for (const resourceAccess of resourceAccesses) { - for (const [, access] of Object.entries(resourceAccess)) { - const zodInputShape = access.type === "params" ? typedDef.params : typedDef.querystring; - assert.notEqual( - zodInputShape?.shape?.[access.key], - undefined, - `${method} ${path} ${resourceType}.${access.type}.${access.key}: does not exists` - ); - } - } - } - } - } - } - }); }); diff --git a/shared/routes/index.ts b/shared/routes/index.ts index ee29800..69ebe63 100644 --- a/shared/routes/index.ts +++ b/shared/routes/index.ts @@ -1,31 +1,20 @@ import { ConditionalExcept, EmptyObject, Jsonify } from "type-fest"; import z, { ZodType } from "zod"; -import { zUserAdminRoutes } from "./admin/admin.routes"; -import { zAuthRoutes } from "./auth.routes"; import { zCerfaRoutes } from "./cerfa.routes"; import { IRouteSchema, IRouteSchemaWrite } from "./common.routes"; import { zControlsRoutes } from "./controls.routes"; import { zCoreRoutes } from "./core.routes"; -import { zEmailRoutes } from "./emails.routes"; import { zGeoRoutes } from "./geo.routes"; import { zNafRoutes } from "./naf.routes"; import { zSiretRoutes } from "./siret.routes"; import { zTcoRoutes } from "./tco.routes"; -import { zUserRoutes } from "./user.routes"; const zRoutesGet = { - ...zUserAdminRoutes.get, - ...zUserRoutes.get, - ...zAuthRoutes.get, ...zCoreRoutes.get, - ...zEmailRoutes.get, } as const; const zRoutesPost = { - ...zUserAdminRoutes.post, - ...zAuthRoutes.post, - ...zEmailRoutes.post, ...zCerfaRoutes.post, ...zControlsRoutes.post, ...zGeoRoutes.post, @@ -76,12 +65,6 @@ export type IQuery = S["querystring"] extends ZodType ? export type IParam = S["params"] extends ZodType ? z.input : never; -type IHeadersAuth = S extends { securityScheme: { auth: infer A } } - ? A extends "access-token" | "api-key" - ? { authorization: `Bearer ${string}` } - : object - : object; - export type IHeaders = S["headers"] extends ZodType ? Omit, "referrer"> : object; @@ -89,7 +72,7 @@ export type IHeaders = S["headers"] extends ZodType type IRequestRaw = { params: IParam; querystring: IQuery; - headers: IHeaders & IHeadersAuth extends EmptyObject ? never : IHeaders & IHeadersAuth; + headers: IHeaders extends EmptyObject ? never : IHeaders; body: S extends IRouteSchemaWrite ? IBody : never; }; diff --git a/shared/routes/naf.routes.ts b/shared/routes/naf.routes.ts index ca97921..3cb9853 100644 --- a/shared/routes/naf.routes.ts +++ b/shared/routes/naf.routes.ts @@ -15,7 +15,6 @@ export const zNafRoutes = { response: { "2xx": z.any(), }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/siret.routes.ts b/shared/routes/siret.routes.ts index c1d28e9..fdfc5e1 100644 --- a/shared/routes/siret.routes.ts +++ b/shared/routes/siret.routes.ts @@ -16,7 +16,6 @@ export const zSiretRoutes = { response: { "2xx": z.any(), }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/tco.routes.ts b/shared/routes/tco.routes.ts index bdcace1..e053bda 100644 --- a/shared/routes/tco.routes.ts +++ b/shared/routes/tco.routes.ts @@ -16,7 +16,6 @@ export const zTcoRoutes = { response: { "2xx": z.any(), }, - securityScheme: null, }, }, } as const satisfies IRoutesDef; diff --git a/shared/routes/user.routes.ts b/shared/routes/user.routes.ts deleted file mode 100644 index 81dda01..0000000 --- a/shared/routes/user.routes.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { z } from "zod"; - -import { IRoutesDef } from "./common.routes"; - -export const zUserRoutes = { - get: { - "/user/generate-api-key": { - method: "get", - path: "/user/generate-api-key", - response: { - "200": z.object({ api_key: z.string() }).strict(), - }, - securityScheme: { - auth: "cookie-session", - access: "admin", - ressources: {}, - }, - }, - }, -} as const satisfies IRoutesDef; diff --git a/ui/app/(application)/admin/layout.tsx b/ui/app/(application)/admin/layout.tsx deleted file mode 100644 index 1083c37..0000000 --- a/ui/app/(application)/admin/layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -"use client"; -import { useAuth } from "context/AuthContext"; -import { useRouter } from "next/navigation"; -import { FC, PropsWithChildren } from "react"; - -const AdminLayout: FC = ({ children }) => { - const { user } = useAuth(); - const { push } = useRouter(); - - if (!user?.is_admin) { - push("/auth/connexion"); - return null; - } - - return <>{children}; -}; - -export default AdminLayout; diff --git a/ui/app/(application)/admin/utilisateurs/[id]/components/UserView.tsx b/ui/app/(application)/admin/utilisateurs/[id]/components/UserView.tsx deleted file mode 100644 index 9f7db99..0000000 --- a/ui/app/(application)/admin/utilisateurs/[id]/components/UserView.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Typography } from "@mui/material"; -import InfoDetails from "components/infoDetails/InfoDetails"; -import { FC } from "react"; -import { IUserPublic } from "shared/models/user.model"; -import { formatDate } from "utils/date.utils"; - -import Breadcrumb, { PAGES } from "../../../../components/breadcrumb/Breadcrumb"; - -interface Props { - user: IUserPublic; -} - -const UserView: FC = ({ user }) => { - return ( - <> - - - Fiche utilisateur - - - "Identifiant", - }, - email: { - header: () => "Email", - }, - is_admin: { - header: () => "Administrateur", - cell: ({ is_admin }) => (is_admin ? "Oui" : "Non"), - }, - has_api_key: { - header: () => "Clé d'API générée", - cell: ({ has_api_key }) => (has_api_key ? "Oui" : "Non"), - }, - api_key_used_at: { - header: () => "Dernière utilisation API", - cell: ({ api_key_used_at }) => { - return api_key_used_at ? formatDate(api_key_used_at, "PPP à p") : "Jamais"; - }, - }, - }} - /> - - ); -}; - -export default UserView; diff --git a/ui/app/(application)/admin/utilisateurs/[id]/page.tsx b/ui/app/(application)/admin/utilisateurs/[id]/page.tsx deleted file mode 100644 index 20022ff..0000000 --- a/ui/app/(application)/admin/utilisateurs/[id]/page.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { apiGet } from "@/utils/api.utils"; - -import UserView from "./components/UserView"; - -interface Props { - params: { id: string }; -} - -const AdminUserViewPage = async ({ params }: Props) => { - const user = await apiGet(`/admin/users/:id`, { params }); - - return ; -}; - -export default AdminUserViewPage; diff --git a/ui/app/(application)/admin/utilisateurs/components/UserList.tsx b/ui/app/(application)/admin/utilisateurs/components/UserList.tsx deleted file mode 100644 index 09528f8..0000000 --- a/ui/app/(application)/admin/utilisateurs/components/UserList.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import Button from "@codegouvfr/react-dsfr/Button"; -import { useQuery } from "@tanstack/react-query"; -import SearchBar from "components/SearchBar"; -import Table from "components/table/Table"; -import { useRouter, useSearchParams } from "next/navigation"; -import { IUserPublic } from "shared/models/user.model"; -import { apiGet } from "utils/api.utils"; -import { formatDate } from "utils/date.utils"; -import { formatUrlWithNewParams, getSearchParamsForQuery } from "utils/query.utils"; - -import { PAGES } from "../../../components/breadcrumb/Breadcrumb"; - -const UserList = () => { - const searchParams = useSearchParams(); - const { push } = useRouter(); - - const { page: page, limit: limit, q: searchValue } = getSearchParamsForQuery(searchParams); - - const { data: users } = useQuery({ - queryKey: ["users", { searchValue, page, limit }], - queryFn: async () => { - const data = await apiGet("/admin/users", { - querystring: { q: searchValue, page, limit }, - }); - - return data; - }, - }); - - const onSearch = (q: string) => { - const url = formatUrlWithNewParams(PAGES.adminUsers().path, searchParams, { - q, - page, - limit, - }); - - push(url); - }; - - return ( - <> - - - (value ? "Oui" : "Non"), - minWidth: 150, - }, - { - field: "api_key_used_at", - headerName: "Dernière utilisation API", - valueGetter: ({ value }) => { - return value ? formatDate(value as unknown as string, "PPP à p") : "Jamais"; - }, - minWidth: 180, - }, - { - field: "actions", - type: "actions", - headerName: "Actions", - getActions: ({ row: { _id } }) => [ - - - - - - - ); -}; -export default ConnexionPage; diff --git a/ui/app/(application)/auth/modifier-mot-de-passe/page.tsx b/ui/app/(application)/auth/modifier-mot-de-passe/page.tsx deleted file mode 100644 index ca03ce9..0000000 --- a/ui/app/(application)/auth/modifier-mot-de-passe/page.tsx +++ /dev/null @@ -1,134 +0,0 @@ -"use client"; - -import Alert from "@codegouvfr/react-dsfr/Alert"; -import PasswordInput from "@codegouvfr/react-dsfr/blocks/PasswordInput"; -import { Button } from "@codegouvfr/react-dsfr/Button"; -import { Box, Typography } from "@mui/material"; -import { useRouter, useSearchParams } from "next/navigation"; -import { useState } from "react"; -import { SubmitHandler, useForm } from "react-hook-form"; -import { IPostRoutes } from "shared"; -import { IStatus } from "shared/routes/auth.routes"; -import { apiPost } from "utils/api.utils"; - -import Breadcrumb, { PAGES } from "../../components/breadcrumb/Breadcrumb"; -import FormContainer from "../components/FormContainer"; -// import { NavLink } from "../../components/NavLink"; - -interface IFormValues extends Zod.input { - password_confirmation: string; -} - -const ModifierMotDePassePage = () => { - const [status, setStatus] = useState(); - const { push } = useRouter(); - const searchParams = useSearchParams(); - - const token = searchParams?.get("passwordToken") ?? ""; - - const { - register, - handleSubmit, - formState: { errors }, - reset, - watch, - } = useForm(); - - if (!token) { - return push(PAGES.homepage().path); - } - - const password = watch("password"); - - const onSubmit: SubmitHandler = async ({ password }) => { - try { - await apiPost("/auth/reset-password", { - headers: { - authorization: `Bearer ${token}`, - }, - body: { - password, - }, - }); - - setStatus({ - error: false, - message: "Votre mot de passe a bien été modifié", - }); - reset(); - - setTimeout(() => { - push("/auth/connexion"); - }, 3000); - } catch (error) { - const errorMessage = (error as Record)?.message; - - setStatus({ - error: true, - message: errorMessage ?? "Impossible de modifier votre mot de passe.", - }); - console.error(error); - } - }; - - return ( - <> - - - - {PAGES.modifierMotDePasse().title} - -
- - value === password || "Les mots de passe ne correspondent pas.", - }, - }), - }} - /> - {status?.message && } - - - - -
- - ); -}; -export default ModifierMotDePassePage; diff --git a/ui/app/(application)/auth/mot-de-passe-oublie/page.tsx b/ui/app/(application)/auth/mot-de-passe-oublie/page.tsx deleted file mode 100644 index 58860b2..0000000 --- a/ui/app/(application)/auth/mot-de-passe-oublie/page.tsx +++ /dev/null @@ -1,87 +0,0 @@ -"use client"; - -import { Alert } from "@codegouvfr/react-dsfr/Alert"; -import { Button } from "@codegouvfr/react-dsfr/Button"; -import { Input } from "@codegouvfr/react-dsfr/Input"; -import { Box, Typography } from "@mui/material"; -import { useState } from "react"; -import { SubmitHandler, useForm } from "react-hook-form"; -import { IGetRoutes, IQuery } from "shared"; -import { IStatus } from "shared/routes/auth.routes"; -import { apiGet } from "utils/api.utils"; - -import Breadcrumb, { PAGES } from "../../components/breadcrumb/Breadcrumb"; -import FormContainer from "../components/FormContainer"; - -type Route = IGetRoutes["/auth/reset-password"]; - -const MotDePasseOubliePage = () => { - const [status, setStatus] = useState(); - const { - register, - handleSubmit, - formState: { errors }, - reset, - } = useForm>(); - - const onSubmit: SubmitHandler> = async (data) => { - try { - await apiGet("/auth/reset-password", { - querystring: data, - }); - - setStatus({ - error: false, - message: "Vous allez recevoir un lien vous permettant de réinitialiser votre mot de passe.", - }); - reset(); - } catch (error) { - const errorMessage = (error as Record)?.message; - - setStatus({ - error: true, - message: - errorMessage ?? - "Impossible de réinitialiser votre mot de passe. Vérifiez que vous avez bien saisi votre adresse email.", - }); - - console.error(error); - } - }; - - return ( - <> - - - - Mot de passe oublié - -
- - - {status?.message && } - - - - - -
- - ); -}; -export default MotDePasseOubliePage; diff --git a/ui/app/(application)/cgu/components/Cgu.tsx b/ui/app/(application)/cgu/components/Cgu.tsx deleted file mode 100644 index 7b585cb..0000000 --- a/ui/app/(application)/cgu/components/Cgu.tsx +++ /dev/null @@ -1,377 +0,0 @@ -import { getLink } from "@codegouvfr/react-dsfr/link"; -import { Summary } from "@codegouvfr/react-dsfr/Summary"; -import { Grid, Typography } from "@mui/material"; -import React, { FC, useEffect } from "react"; - -import Section from "../../components/section/Section"; - -export const cguVersion = "v0.1"; - -const anchors = { - ChampApplication: "champ-application", - Objet: "objet", - Definition: "definition", - FonctionnaliteLieesAuxComptesDesUtilisateurs: "fonctionnalite-liees-aux-comptes-des-utilisateurs", - PresentationDesServices: "presentation-des-services", - Securite: "securite", - Hyperliens: "hyperliens", - Responsabilites: "responsabilites", - MiseAjourDesConditionsUtilisation: "mise-a-jour-des-conditions-utilisation", -}; - -const summaryData = [ - { - anchorName: "Article 1 - Champ d’application", - anchorLink: "champ-application", - }, - { anchorName: "Article 2 - Objet", anchorLink: "objet" }, - { - anchorName: "Article 3 - Définitions", - anchorLink: "definition", - }, - { - anchorName: "Article 4 - Fonctionnalités liées aux comptes des utilisateurs", - anchorLink: "fonctionnalite-liees-aux-comptes-des-utilisateurs", - }, - { - anchorName: "Article 5 - Présentation des services", - anchorLink: "presentation-des-services", - }, - { - anchorName: "Article 6 - Sécurité", - anchorLink: "securite", - }, - { - anchorName: "Article 7 - Hyperliens", - anchorLink: "hyperliens", - }, - { - anchorName: "Article 8 - Responsabilités", - anchorLink: "responsabilites", - }, - { - anchorName: "Article 9 - Mise à jour des conditions d'utilisation", - anchorLink: "mise-a-jour-des-conditions-utilisation", - }, -]; - -interface Props { - onLoad?: () => void; -} - -const { Link } = getLink(); - -const Cgu: FC = ({ onLoad }) => { - useEffect(() => { - onLoad?.(); - }, [onLoad]); - - return ( - - - ({ - linkProps: { - href: `#${item.anchorLink}`, - }, - text: item.anchorName, - }))} - /> - - - - CONDITIONS GÉNÉRALES D'UTILISATION - - Dernière mise à jour le : 3 novembre 2022 - {cguVersion} - - Les présentes conditions générales d’utilisation (dites « CGU ») définissent les conditions d’accès et - d’utilisation des Services par l’Utilisateur. - - -
- - Article 1 – Champ d’application - - - Le tableau de bord est d’accès libre et gratuit à tout Utilisateur. La simple visite du tableau de bord - suppose l’acceptation par tout Utilisateur des présentes conditions générales d’utilisation. - -
-
- - Article 2 – Objet - - - Le tableau de bord a pour objectif de mettre à disposition des différents acteurs les données clés de - l’apprentissage en temps réel. - -
-
- - Article 3 – Définitions - - - Les termes ci-dessous définis ont entre les parties la signification suivante : -
-
- « Utilisateur » : toute personne ayant accès aux services du tableau de bord -
-
- « Authentification » : fonctionnalité qui permet aux utilisateurs titulaires d'un - compte d'accéder aux services proposés sur le tableau de bord. -
-
- « Services » : ensemble des prestations proposées sur le tableau de bord. Elles sont les - suivantes : création d'un compte utilisateur, consultation des données, export des données, saisie de - données, accès à la documentation. -
-
- « Tableau de bord » : service en ligne permettant de consulter, exporter, saisir des - données. -
-
-
-
-
- - Article 4 – Fonctionnalités liées aux comptes des utilisateurs - - - L'accès à certaines données du tableau de bord est restreint à une inscription à un compte : - - https://cfas.apprentissage.beta.gouv.fr/login - - . Les services proposés ne sont accessibles qu'aux seuls utilisateurs munis d'un identifiant - d'authentification et d'un mot de passe. -
-
- De la même façon, la connexion au compte permet d’accéder, de façon contextualisée selon le profil de - l’utilisateur à tout ou partie des fonctionnalités. -
-
- La procédure de création de compte permet aux utilisateurs de se créer un compte associé à leur type de - profil et d'accéder aux fonctionnalités de consultation de certaines données, d’export des données et - de saisie de données. -
-
- L'utilisateur est titulaire d'un compte personnel, accessible par son identifiant personnel et par - un mot de passe dès lors que toutes les formalités nécessaires à son inscription sont accomplies. -
-
- Un seul compte peut être attribué par utilisateur (même adresse électronique). -
-
- Le mot de passe est strictement personnel et confidentiel. Il contient au moins 12 caractères comprenant - majuscules, minuscules, chiffres, et caractères spéciaux. -
-
- En cas d'oubli de son mot de passe ou de compromission, l’utilisateur utilise la fonctionnalité « oubli - de mot de passe » et suit les instructions fournies par le tableau de bord. -
-
-
- - Article 5 – Présentation des services - - - Le tableau de bord permet aux utilisateurs : -
-
- - de consulter des données de l’apprentissage à des fins de pilotage ; -
- - d’exporter des fichiers de données de l’apprentissage ; -
- - de s’informer sur les données de l’apprentissage exposées sur le tableau de bord ; -
- - de consulter des listes nominatives d’apprentis en situation de rupture ou d’abandon à des fins - d’accompagnement ; -
- - de déposer des fichiers de données pour alimenter les chiffres du tableau de bord ; -
- - d’exposer certaines données sur leurs interfaces à l’aide d’une API dont la documentation est mise à - disposition par la Mission interministérielle de l’apprentissage ; -
- - d’exposer leurs données sur le tableau de bord à l’aide d’une API dont la documentation est mise à - disposition par la Mission interministérielle de l’apprentissage. -
-
- Le tableau de bord est, en principe, accessible en permanence. -
-
- La Mission interministérielle de l’apprentissage se réserve le droit, sans préavis, ni indemnité, de fermer - temporairement l'accès à un ou plusieurs services du tableau de bord pour effectuer une mise à jour, - des modifications ou changements sur les méthodes opérationnelles, les serveurs et les heures - d'accessibilité. Cette liste n'est pas limitative. -
-
- Dans ce cas, la Mission interministérielle de l’apprentissage peut indiquer une date de réouverture du - compte ou d'accessibilité à un ou plusieurs services. -
-
-
- - Article 6 - Sécurité - - - Le tableau de bord comporte un accès sécurisé qui permet de consulter certaines données. Tout accès - frauduleux est interdit et sanctionné pénalement. Il en est de même pour toute entrave ou altération du - fonctionnement de ce système, ou en cas d'introduction, de suppression ou de modification des données - qui y sont contenues. -
-
- L'utilisateur s'engage à ne pas perturber le bon fonctionnement de ce système. Il veille notamment - à ne pas introduire de virus ou toute autre technologie nuisible au tableau de bord. -
-
- La Mission interministérielle de l’apprentissage fait ses meilleurs efforts, conformément aux règles de - l'art, pour sécuriser le service eu égard à la complexité de l'internet. -
-
-
- - Article 7 – Hyperliens - - - La Mission interministérielle de l’apprentissage se réserve la possibilité de mettre en place des hyperliens - sur le tableau de bord donnant accès à des pages internet autres que celles de son interface. -
-
- Les utilisateurs sont formellement informés que les sites auxquels ils peuvent accéder par - l'intermédiaire des liens hypertextes n’appartiennent pas tous à la Mission interministérielle de - l’apprentissage. -
-
- La Mission interministérielle de l’apprentissage ne saurait être responsable de l'accès par les - utilisateurs par les liens hypertextes mis en place dans le cadre du tableau de bord à d'autres - ressources présentes sur le réseau. -
-
- La Mission interministérielle de l’apprentissage décline toute responsabilité quant au contenu des - informations fournies sur ces ressources présentes sur le réseau au titre de l'activation des liens - hypertextes. -
-
-
- - Article 8 – Responsabilités - - - 8.1. Limites de la responsabilité de la Mission interministérielle de l’apprentissage - - - La Mission interministérielle de l’apprentissage ne saurait être tenue pour responsable des conséquences - provoquées par le caractère erroné ou frauduleux des informations fournies par l'utilisateur. -
-
- L'utilisateur reste en toute circonstance responsable de l'utilisation qu'il fait des - services du tableau de bord. La Mission interministérielle de l’apprentissage ne saurait être responsable de - l'impossibilité d'utiliser le tableau de bord et les services. -
-
- La Mission interministérielle de l’apprentissage ne saurait être responsable des atteintes à la sécurité - informatique pouvant causer des dommages aux matériels informatiques des utilisateurs et à leurs données. -
-
- La Mission interministérielle de l’apprentissage n'est pas responsable des conditions - d'utilisation du service par les utilisateurs. -
-
- La responsabilité de la Mission interministérielle de l’apprentissage ne saurait être recherchée en cas - d'usage frauduleux ou abusif ou, à la suite d'une divulgation volontaire ou involontaire, à - quiconque, des codes d'accès confiés à l'utilisateur. -
-
- La responsabilité de la Mission interministérielle de l’apprentissage ne peut être engagée en cas de - dommages directs ou indirects résultant de l'utilisation du tableau de bord. -
-
- La responsabilité de la Mission interministérielle de l’apprentissage ne pourra être recherchée ni retenue - en cas d'indisponibilité temporaire ou totale de tout ou partie de l'accès au tableau de bord, - d'une difficulté liée au temps de réponse et d'une manière générale, d'un défaut de - performance quelconque. -
-
- - 8.2. Responsabilité des utilisateurs - - -
- L'utilisateur s'engage à utiliser le tableau de bord et les services, ainsi que l'ensemble - des informations auxquelles il pourra avoir accès en conformité avec les stipulations des présentes - conditions générales d'utilisation. -
-
- L'utilisateur est seul responsable de la préservation et de la confidentialité de son mot de passe et - autres données confidentielles qui lui seraient éventuellement transmises par la Mission interministérielle - de l’apprentissage. -
-
- L'utilisateur est responsable de la sincérité des informations qu'il fournit et s'engage à - mettre à jour les informations le concernant ou à aviser la Mission interministérielle de l’apprentissage - sans délai de toute modification affectant sa situation. -
-
- En cas d'utilisation frauduleuse de son compte ou vol de son mot de passe, l'utilisateur - s'engage à prévenir immédiatement la Mission interministérielle de l’apprentissage et à modifier sans - délai son mot de passe. -
-
- Cette notification devra être adressée à la Mission interministérielle de l’apprentissage par courrier - électronique à l'adresse : tableau-de-bord@apprentissage.beta.gouv.fr. La date de réception de ce - courrier électronique fera foi entre les parties. -
-
- L'utilisateur s'engage à ne pas perturber l'usage que pourraient faire les autres - utilisateurs du tableau de bord, de ne pas accéder aux comptes membres tiers et de ne pas accéder à des - parties du tableau de bord dont l'accès est réservé. -
-
- L'utilisateur s'engage à utiliser le service ainsi que l'ensemble des informations auxquelles - il pourra avoir accès, dans un but conforme à l'ordre public, aux bonnes mœurs et aux droits des tiers. -
-
- L'utilisateur s'engage à ne commettre aucun acte pouvant mettre en cause la sécurité informatique - de la Mission interministérielle de l’apprentissage ou des autres utilisateurs. -
-
- L'utilisateur s'engage à ne pas interférer ou interrompre le fonctionnement normal du tableau de - bord. -
-
- L'utilisateur s'engage à ne pas collecter, utiliser, ou effectuer un traitement quelconque des - données personnelles des autres utilisateurs. -
-
- Toute utilisation frauduleuse ou hors usage initial du tableau de bord est interdite. -
-
- L'Utilisateur s'engage à ne pas commercialiser les données reçues et à ne pas les communiquer à - des tiers en dehors des cas prévus par la loi. -
-
- L'Utilisateur s'engage à ne pas mettre en ligne des contenus ou informations contraires aux - dispositions légales et réglementaires en vigueur susceptibles de mettre en péril le fonctionnement du - tableau de bord. -
-
- Toute tentative d'accès non autorisé aux services, à d'autres comptes, aux systèmes informatiques - ou à d'autres réseaux connectés ou à l'un des services via le piratage ou toute autre méthode est - interdite. -
-
-
- - Article 9 – Mise à jour des conditions d’utilisation - - - Les termes des CGU doivent être acceptés au moment de la connexion. Toute modification des CGU réalisée en - fonction des modifications apportées au site, de l’évolution de la législation ou pour tout autre motif jugé - nécessaire, nécessite votre consentement. - -
-
- - ); -}; - -export default Cgu; diff --git a/ui/app/(application)/cgu/page.tsx b/ui/app/(application)/cgu/page.tsx deleted file mode 100644 index 9ab1e18..0000000 --- a/ui/app/(application)/cgu/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -"use client"; - -import Breadcrumb, { PAGES } from "../components/breadcrumb/Breadcrumb"; -import Cgu from "./components/Cgu"; - -const CGUPage = () => { - return ( - <> - - - - ); -}; -export default CGUPage; diff --git a/ui/app/(application)/components/breadcrumb/Breadcrumb.tsx b/ui/app/(application)/components/breadcrumb/Breadcrumb.tsx index c4ebbaa..053be75 100644 --- a/ui/app/(application)/components/breadcrumb/Breadcrumb.tsx +++ b/ui/app/(application)/components/breadcrumb/Breadcrumb.tsx @@ -18,10 +18,6 @@ export const PAGES = { title: "Conditions Générales d'Utilisation", path: "https://cfas.apprentissage.beta.gouv.fr/cgu", }), - donneesPersonnelles: () => ({ - title: "Données Personnelles", - path: "/donnees-personnelles", - }), politiqueConfidentialite: () => ({ title: "Politique de Confidentialité", path: "https://cfas.apprentissage.beta.gouv.fr/politique-de-confidentialite", @@ -30,43 +26,6 @@ export const PAGES = { title: "Statistiques", path: "/stats", }), - connexion: () => ({ - title: "Se connecter", - path: "/auth/connexion", - }), - motDePasseOublie: () => ({ - title: "Mot de passe oublié", - path: "/auth/mot-de-passe-oublie", - }), - modifierMotDePasse: () => ({ - title: "Modifier mon mot de passe", - path: "/modifier-mot-de-passe", - }), - compteProfil: () => ({ - title: "Mon profil", - path: "/compte/profil", - }), - nouveauDossier: () => ({ - title: "Nouveau dossier", - path: "/dossiers/nouveau", - }), - adminFichier: () => ({ - title: "Gestion des fichiers", - path: "/admin/fichier", - }), - adminImport: () => ({ - title: "Import de fichier", - path: "/admin/fichier/import", - }), - adminUsers: () => ({ - title: "Gestion des utilisateurs", - path: "/admin/utilisateurs", - }), - adminUserView: (id: string) => ({ - title: "Fiche utilisateur", - path: `/admin/utilisateurs/${id}`, - }), - cerfa: () => ({ title: "Cerfa", path: "/cerfa", diff --git a/ui/app/(application)/components/header/Header.tsx b/ui/app/(application)/components/header/Header.tsx index 99b5f0e..4b2e2be 100644 --- a/ui/app/(application)/components/header/Header.tsx +++ b/ui/app/(application)/components/header/Header.tsx @@ -1,50 +1,12 @@ -import { Header as DSFRHeader, HeaderProps } from "@codegouvfr/react-dsfr/Header"; -import { useAuth } from "context/AuthContext"; -import { usePathname, useRouter } from "next/navigation"; -import { apiGet } from "utils/api.utils"; +import { Header as DSFRHeader } from "@codegouvfr/react-dsfr/Header"; +import { usePathname } from "next/navigation"; -import { PAGES } from "../breadcrumb/Breadcrumb"; import { getNavigationItems } from "./header.utils"; export const Header = () => { - const { user, setUser } = useAuth(); - const { push } = useRouter(); const pathname = usePathname(); - const handleLogout = async () => { - await apiGet("/auth/logout", {}); - setUser(); - push(PAGES.homepage().path); - }; - - const navigation = getNavigationItems({ user, pathname }); - - const _loggedOut: HeaderProps.QuickAccessItem[] = [ - { - iconId: "fr-icon-lock-line", - linkProps: { - href: PAGES.connexion().path, - }, - text: "Se connecter", - }, - ]; - - const _loggedIn: HeaderProps.QuickAccessItem[] = [ - { - linkProps: { - href: PAGES.compteProfil().path, - }, - iconId: "fr-icon-account-line", - text: "Mon compte", - }, - { - buttonProps: { - onClick: handleLogout, - }, - text: "Se deconnecter", - iconId: "fr-icon-logout-box-r-line", - }, - ]; + const navigation = getNavigationItems({ pathname }); return ( { - let navigation: MainNavigationProps.Item[] = [ +export const getNavigationItems = ({ pathname }: GetNavigationItemsProps): MainNavigationProps.Item[] => { + const navigation: MainNavigationProps.Item[] = [ { isActive: pathname === PAGES.homepage().path, text: "Accueil", @@ -26,32 +24,6 @@ export const getNavigationItems = ({ user, pathname }: GetNavigationItemsProps): }, ]; - if (user?.is_admin) { - navigation = [ - ...navigation, - { - text: "Administration", - isActive: [PAGES.adminUsers().path, PAGES.adminFichier().path].includes(pathname), - menuLinks: [ - { - text: PAGES.adminUsers().title, - isActive: pathname === PAGES.adminUsers().path, - linkProps: { - href: PAGES.adminUsers().path, - }, - }, - { - text: PAGES.adminFichier().title, - isActive: pathname === PAGES.adminFichier().path, - linkProps: { - href: PAGES.adminFichier().path, - }, - }, - ], - }, - ]; - } - return navigation.map((item) => { const { menuLinks } = item; diff --git a/ui/app/(application)/compte/profil/page.tsx b/ui/app/(application)/compte/profil/page.tsx deleted file mode 100644 index 42b1cf3..0000000 --- a/ui/app/(application)/compte/profil/page.tsx +++ /dev/null @@ -1,134 +0,0 @@ -"use client"; - -import Button from "@codegouvfr/react-dsfr/Button"; -import Input from "@codegouvfr/react-dsfr/Input"; -import { createModal } from "@codegouvfr/react-dsfr/Modal"; -import { Box, Typography } from "@mui/material"; -import { useState } from "react"; - -import InfoDetails from "../../../../components/infoDetails/InfoDetails"; -import Toast, { useToast } from "../../../../components/toast/Toast"; -import { useAuth } from "../../../../context/AuthContext"; -import { apiGet } from "../../../../utils/api.utils"; -import { formatDate } from "../../../../utils/date.utils"; -import Breadcrumb, { PAGES } from "../../components/breadcrumb/Breadcrumb"; - -const modal = createModal({ - id: "generate-api-key", - isOpenedByDefault: false, -}); - -const ProfilPage = () => { - const { user } = useAuth(); - const [apiKey, setApiKey] = useState(); - const { toast, setToast, handleClose } = useToast(); - - const handleClick = () => { - if (apiKey) { - navigator.clipboard.writeText(apiKey); - setToast({ - severity: "success", - message: "Jeton API copié dans le presse-papier.", - }); - } - }; - - const generateApiKey = async () => { - try { - const data = await apiGet("/user/generate-api-key", {}); - - setApiKey(data.api_key); - } catch (error) { - console.error(error); - setToast({ - severity: "error", - message: "Une erreur est survenue lors de la génération du jeton API.", - }); - } finally { - modal.close(); - } - }; - - if (!user) return null; - - return ( - <> - - - Mon compte - - "Adresse email", - }, - is_admin: { - header: () => "Accès", - cell: (data) => (data.is_admin ? "Administrateur" : "Utilisateur"), - }, - }} - /> - - Jeton API - - {user.has_api_key || - (apiKey && ( - - ))} - {apiKey && ( - <> - - Ce jeton n'est visible qu'une fois, il est recommandé de le stocker dans un endroit sécurisé. - - - - - - )} - - {(user.has_api_key || apiKey) && ( - - {user.api_key_used_at ? ( - <>{`Dernière utilisation le ${formatDate(user.api_key_used_at as unknown as string, "PPP à p")}`} - ) : ( - <>Ce jeton n'a pas encore été utilisé - )} - - )} - - { - generateApiKey(); - }, - children: "Générer", - }, - ]} - > - Êtes-vous sûr de vouloir générer un nouveau jeton API ? Le jeton existant ne sera plus utilisable. - - - - - - - - - ); -}; - -export default ProfilPage; diff --git a/ui/app/(application)/donnees-personnelles/components/DonneesPersonnelles.tsx b/ui/app/(application)/donnees-personnelles/components/DonneesPersonnelles.tsx deleted file mode 100644 index 52bdfa6..0000000 --- a/ui/app/(application)/donnees-personnelles/components/DonneesPersonnelles.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import { fr } from "@codegouvfr/react-dsfr"; -import { Summary } from "@codegouvfr/react-dsfr/Summary"; -import { Grid, Typography } from "@mui/material"; -import React from "react"; - -import Section from "../../components/section/Section"; - -const anchors = { - mission: "mission", - finalite: "finalite", - minimisation: "minimisation", -}; - -const summaryData = [ - { - anchorLink: anchors.mission, - anchorName: "La mission d’intérêt public", - }, - { - anchorLink: anchors.finalite, - anchorName: "Faciliter le pilotage opérationnel de l’apprentissage", - }, - { - anchorLink: anchors.minimisation, - anchorName: "Minimisation des données", - }, -]; - -const DonneesPersonnelles = () => { - const productName = "CERFA Contrat d'apprentissage"; - - return ( - - - ({ - linkProps: { - href: `#${item.anchorLink}`, - }, - text: item.anchorName, - }))} - /> - - - - Protection des données à caractère personnel - - - Le contrat est{" "} - - construit dans le respect de la vie privée des personnes et applique les standards de sécurité de - l'État. - - - -
- - Base légale - - - La mission d'intérêt public - - - - Il existe plusieurs bases légales pour fonder un traitement de données à caractère personnel : - -
    -
  • Le consentement des personnes ;
  • -
  • Une obligation légale ;
  • -
  • L’existence d’un contrat ;
  • -
  • Une mission d’intérêt public, etc...
  • -
- - C’est sur cette dernière base légale que se fonde notre traitement. En effet, la Mission a accès à certaines - données à caractère personnel (état civil, coordonnées, code formation, statut inscrit, apprenti, ou - abandon) enregistrées dans les systèmes de gestion des CFA pour les années n et n-1, afin de proposer des - nouveaux services, de réaliser des études de cohorte et des analyses de données pour améliorer la qualité du - service public rendu. - - - Le traitement de collecte des données relatives aux candidats à l’apprentissage et aux apprentis s’inscrit - dans une mission d’intérêt public décrite dans le cadre de la mission Houzel. Cette mission Houzel fait - l’objet de deux lettres en date du 10 septembre 2019 puis du 25 février 2020, mais aussi de deux décisions - du gouvernement en date du 26 novembre 2019 et du 15 octobre 2020. - -
- - {/* Block Faciliter le pilotage */} -
- - Finalité - - - Faciliter le pilotage opérationnel de l'apprentissage - - - - Le {productName} vise à mettre à disposition de toutes les parties prenantes de la formation en - apprentissage les données clés, de manière dynamique, afin de permettre un pilotage opérationnel réactif - dans les territoires. - - - L’affichage des données en temps réel auprès des acteurs institutionnels leur permet : - -
    -
  • - D'avoir une tendance de l’évolution du nombre d’apprentis ; -
  • -
  • - De dénombrer et identifier les CFAs dans lesquels des jeunes sont en recherche de contrat - ou en risque de décrochage ; -
  • -
  • - D'évaluer l’impact des plans d’actions régionaux. -
  • -
-
- - {/* Block Minimisation des données */} -
- - Données collectées - - - Minimisation des données - - - - Dans le respect du RGPD, seules les données utiles à la construction du {productName} sont collectées. - - Données concernant l’apprenant : -
    -
  • - Identification : nom, prénom, date de naissance, tel, e-mail, Code Insee résidence, INE ; -
  • -
  • - Formation suivie : Code Formation Diplôme, RNCP, libellé, période de la formation, année - dans la formation, année scolaire, date début de formation ; -
  • -
  • - Le statut de l’apprenant : apprenti, inscrit sans contrat, rupturant, abandon -
  • -
- Données concernant l’organisme : -
    -
  • - Identification : UAI, SIRET, Nom, Code Insee CFA Formateur -
  • -
- Données concernant le contrat d'apprentissage : -
    -
  • Date de début et date de fin
  • -
-
-
- - ); -}; - -export default DonneesPersonnelles; diff --git a/ui/app/(application)/donnees-personnelles/page.tsx b/ui/app/(application)/donnees-personnelles/page.tsx deleted file mode 100644 index 353f9ce..0000000 --- a/ui/app/(application)/donnees-personnelles/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -"use client"; - -import Breadcrumb, { PAGES } from "../components/breadcrumb/Breadcrumb"; -import DonneesPersonnelles from "./components/DonneesPersonnelles"; - -const DonneesPersonnellesPage = () => { - return ( - <> - - - - ); -}; -export default DonneesPersonnellesPage; diff --git a/ui/app/(application)/layout.tsx b/ui/app/(application)/layout.tsx index a06e2bf..5b81aca 100644 --- a/ui/app/(application)/layout.tsx +++ b/ui/app/(application)/layout.tsx @@ -4,30 +4,13 @@ import "react-notion-x/src/styles.css"; import { DsfrHead } from "@codegouvfr/react-dsfr/next-appdir/DsfrHead"; import { DsfrProvider } from "@codegouvfr/react-dsfr/next-appdir/DsfrProvider"; import { getHtmlAttributes } from "@codegouvfr/react-dsfr/next-appdir/getHtmlAttributes"; -import { AuthContextProvider } from "context/AuthContext"; import { Metadata } from "next"; import Link from "next/link"; import { PropsWithChildren } from "react"; -import { IUserPublic } from "shared/models/user.model"; import { defaultColorScheme } from "theme/defaultColorScheme"; -import { apiGet } from "utils/api.utils"; import { StartDsfr } from "../StartDsfr"; -async function getSession(): Promise { - if (process.env.NEXT_PHASE === "phase-production-build") { - return; - } - - try { - const session: IUserPublic = await apiGet(`/auth/session`, {}); - return session; - } catch (error) { - console.log(error); - return; - } -} - export const metadata: Metadata = { viewport: "width=device-width, initial-scale=1", icons: { @@ -41,7 +24,6 @@ export const metadata: Metadata = { }; export default async function RootLayout({ children }: PropsWithChildren) { - const session = await getSession(); const lang = "fr"; return ( @@ -64,9 +46,7 @@ export default async function RootLayout({ children }: PropsWithChildren) { /> - - {children} - + {children} ); diff --git a/ui/app/(application)/mentions-legales/components/MentionLegales.tsx b/ui/app/(application)/mentions-legales/components/MentionLegales.tsx deleted file mode 100644 index ac7932b..0000000 --- a/ui/app/(application)/mentions-legales/components/MentionLegales.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { Summary } from "@codegouvfr/react-dsfr/Summary"; -import { Grid, Typography } from "@mui/material"; - -import Section from "../../components/section/Section"; - -const anchors = { - EditeurDuSite: "editeur-du-site", - DirecteurDeLaPublication: "directeur-de-la-publication", - HebergementDuSite: "hebergement-du-site", - Accessibilite: "accessibilite", - SignalerUnDyfonctionnement: "signaler-un-dyfonctionnement", -}; - -const summaryData = [ - { - anchorName: "Éditeur du site", - anchorLink: anchors.EditeurDuSite, - }, - { - anchorName: "Directeur de la publication", - anchorLink: anchors.DirecteurDeLaPublication, - }, - { - anchorName: "Hébergement du site", - anchorLink: anchors.HebergementDuSite, - }, - { - anchorName: "Accessibilité", - anchorLink: anchors.Accessibilite, - }, - { - anchorName: "Signaler un dysfonctionnement", - anchorLink: anchors.SignalerUnDyfonctionnement, - }, -]; - -const MentionsLegales = () => { - return ( - - - ({ - linkProps: { - href: `#${item.anchorLink}`, - }, - text: item.anchorName, - }))} - /> - - - - Mentions légales - - - Mentions légales du site « Contrat » - -
- - Éditeur du site - - - Ce site est édité par la Délégation Générale à l’Emploi et à la Formation Professionnelle (DGEFP) et la - Mission interministérielle de l’apprentissage. -
-
- 10-18 place des 5 Martyrs du Lycée Buffon -
75015 Paris -
-
- -
- - Directeur de la publication - - - Le Directeur de la publication est Monsieur Bruno Lucas, Délégué général à l’Emploi et à la Formation - Professionnelle. - -
- -
- - Hébergement du site - - - L’hébergement est assuré par OVH SAS, situé à l’adresse suivante : -
- 2 rue Kellermann -
- 59100 Roubaix -
- Standard : 09.72.10.07 -
-
- La conception et la réalisation du site sont effectuée par La Mission Interministérielle pour - l’apprentissage, située à l’adresse suivante : -
- Beta.gouv -
- 20 avenue de Ségur -
- 75007 Paris -
-
- -
- - Accessibilité - - - La conformité aux normes d’accessibilité numérique est un objectif ultérieur mais nous tâchons de rendre ce - site accessible à toutes et à tous. - -
- -
- - Signaler un dysfonctionnement - - - Si vous rencontrez un défaut d’accessibilité vous empêchant d’accéder à un contenu ou une fonctionnalité du - site, merci de nous en faire part. -
- Si vous n’obtenez pas de réponse rapide de notre part, vous êtes en droit de faire parvenir vos doléances ou - une demande de saisine au Défenseur des droits. -
-
-
- - ); -}; - -export default MentionsLegales; diff --git a/ui/app/(application)/mentions-legales/page.tsx b/ui/app/(application)/mentions-legales/page.tsx deleted file mode 100644 index 55e7559..0000000 --- a/ui/app/(application)/mentions-legales/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -"use client"; - -import Breadcrumb, { PAGES } from "../components/breadcrumb/Breadcrumb"; -import MentionsLegales from "./components/MentionLegales"; - -const MentionsLegalesPage = () => { - return ( - <> - - - - ); -}; -export default MentionsLegalesPage; diff --git a/ui/app/(application)/politique-confidentialite/components/PolitiqueConfidentialite.tsx b/ui/app/(application)/politique-confidentialite/components/PolitiqueConfidentialite.tsx deleted file mode 100644 index a2cec2e..0000000 --- a/ui/app/(application)/politique-confidentialite/components/PolitiqueConfidentialite.tsx +++ /dev/null @@ -1,278 +0,0 @@ -import { getLink } from "@codegouvfr/react-dsfr/link"; -import Summary from "@codegouvfr/react-dsfr/Summary"; -import Table from "@codegouvfr/react-dsfr/Table"; -import { Grid, Typography } from "@mui/material"; -import React from "react"; - -import Section from "../../components/section/Section"; - -const CONTACT_ADDRESS = "tableau-de-bord@apprentissage.beta.gouv.fr"; - -const { Link } = getLink(); - -const anchors = { - Finalite: "finalite", - DonneesACaracterePersonelTraitees: "donnees-a-caractere-personel-traitees", - BaseJuridiqueDuTraitementDeDonnees: "base-juridique-du-traitement-de-donnees", - DureeDeConservation: "duree-de-conservation", - DroitDesPersonnesConcernees: "droit-des-personnes-concernees", - DestinatairesDesDonnees: "destinataires-des-donnees", - SecuriteEtConfidentialiteDesDonnees: "securite-et-confidentialite-des-donnees", -}; - -const summaryData = [ - { anchorName: "Finalité", anchorLink: "finalite" }, - { - anchorName: "Données à caractère personnel traitées", - anchorLink: "donnees-a-caractere-personel-traitees", - }, - { - anchorName: "Base juridique du traitement de données", - anchorLink: "base-juridique-du-traitement-de-donnees", - }, - { - anchorName: "Durée de conservation", - anchorLink: "duree-de-conservation", - }, - { - anchorName: "Droit des personnes concernées", - anchorLink: "droit-des-personnes-concernees", - }, - { - anchorName: "Destinataires des données", - anchorLink: "destinataires-des-donnees", - }, - { - anchorName: "Sécurité et confidentialité des données", - anchorLink: "securite-et-confidentialite-des-donnees", - }, -]; - -const PolitiqueDeConfidentialite = () => { - return ( - - - ({ - linkProps: { - href: `#${item.anchorLink}`, - }, - text: item.anchorName, - }))} - /> - - - - Politique de confidentialité - - -
- - Traitement des données à caractère personnel - - - Le tableau de bord de l’apprentissage est développé par la Mission nationale pour l’apprentissage, mandatée - par le ministère du Travail. - -
- -
- - Finalités - - - Nous manipulons des données à caractère personnel pour améliorer la qualité du suivi et du pilotage de - l’apprentissage par les différents acteurs. Plus précisément, elles visent à : - -
    -
  • - Produire sous la forme d’un tableau de bord les données synthétiques des effectifs de l'apprentissage - afin de contribuer au pilotage de l’apprentissage au niveau national et territorial par les acteurs - publics ou avec délégation de service public ; -
  • -
  • - Identifier les jeunes en recherche de contrat ou en situation de décrochage pour améliorer leur - accompagnement ; -
  • -
  • - Produire les données nécessaires aux organismes de formation pour répondre aux enquêtes (notamment SIFA) ; -
  • -
  • Créer un compte pour accéder ou fournir des données;
  • -
  • Suivre et piloter l'usage du tableau de bord par l'équipe Mission apprentissage ;
  • -
  • Identifier les organismes de formation et leurs réseaux (référentiel).
  • -
-
-
- - Données à caractère personnel traitées - - - Nous traitons les données à caractère personnel et catégories de données à caractère personnel suivantes : - -
    -
  • - Données relatives à l’identification du candidat ou jeune (nom, prénom, date de naissance, INE, adresse - e-mail) ; -
  • -
  • Données relatives au représentant légal du jeune (nom, numéro de téléphone) ;
  • -
  • - Données relatives aux évènements du parcours des apprenants (date de début et de fin, date de début fin de - contrat, et rupture, organisme de formation et département) ; -
  • -
  • Informations relatives au souhait de formation des candidats ;
  • -
  • Données de contact des organisme de formation (adresse e-mail) ;
  • -
  • Données de contact des entreprises (adresse e-mail).
  • -
-
-
- - Base juridique du traitement de données - - - Nous sommes autorisés à traiter vos données dans le cadre d’une mission d’intérêt public ou relevant de - l’exercice de l’autorité publique dont est investi le responsable de traitement au sens de l’article 6-e du - RPGD. Cette mission est notamment précisée dans la lettre de Mission de la Mission nationale pour - l’apprentissage du 10 septembre 2019 et décision gouvernementale du 26 novembre 2019. - -
-
- - Durée de conservation - - - Nous conservons vos données pour une durée de 2 ans à compter de la dernière modification liée aux - informations sur un candidat. - -
-
- - Droit des personnes concernées - - Vous disposez des droits suivants concernant vos données à caractère personnel : -
    -
  • Droit d’information et droit d’accès aux données ;
  • -
  • Droit de rectification des données ;
  • -
  • Droit d’opposition au traitement de données ;
  • -
  • Droit à la limitation des données.
  • -
- -
- Pour les exercer, faites-nous parvenir une demande en précisant la date et l’heure précise de la requête – - ces éléments sont indispensables pour nous permettre de retrouver votre recherche – par voie électronique à - l’adresse suivante : {CONTACT_ADDRESS} -
-
- Par voie postale : -
-
- Délégation générale à l’emploi et à la formation professionnelle -
- 14 avenue Duquesne -
- 75350 Paris SP 07 -
-
- En raison de l’obligation de sécurité et de confidentialité dans le traitement des données à caractère - personnel qui incombe au responsable de traitement, votre demande ne sera traitée que si vous apportez la - preuve de votre identité.
- Pour vous aider dans votre démarche, vous trouverez ici -
- - https://www.cnil.fr/fr/modele/courrier/exercer-son-droit-dacces - - , un modèle de courrier élaboré par la CNIL. -
-
- Le responsable de traitement s’engage à répondre dans un délai raisonnable qui ne saurait dépasser 1 mois à - compter de la réception de votre demande. -
-
-
- - Destinataires des données - - - Nous nous engageons à ce que les données à caractères personnels soient traitées par les seules personnes - autorisées. - -
- Ont accès aux données : -
    -
  • Les agents autorisés des DREETS, dans le cadre de leurs missions de service public ;
  • -
  • Les organismes de formation ;
  • -
  • Les réseaux d’organismes de formation ;
  • -
  • Les Régions ;
  • -
  • Les personnes autorisées au sein des Rectorats, dans le cadre de leurs missions de service public ;
  • -
  • Les personnes autorisées au sein des Académies, dans le cadre de leurs missions de service public ;
  • -
  • - Les personnes autorisées travaillant pour le compte de la mission interministérielle pour l’apprentissage - dans le cadre de la conception des services numériques ; -
  • -
  • - Les personnes travaillant pour le compte de la mission interministérielle pour l’apprentissage dans le - cadre de propositions ciblées d'offres d’emploi ou d’alternance ; -
  • -
-
-
- - Sécurité et confidentialité des données - - - Les mesures techniques et organisationnelles de sécurité adoptées pour assurer la confidentialité, - l’intégrité et protéger l’accès des données sont notamment : - -
    -
  • Anonymisation ;
  • -
  • Stockage des données en base de données ;
  • -
  • Stockage des mots de passe en base sont hachés ;
  • -
  • Cloisonnement des données ;
  • -
  • Mesures de traçabilité ;
  • -
  • Surveillance ;
  • -
  • Protection contre les virus, malwares et logiciels espions ;
  • -
  • Protection des réseaux ;
  • -
  • Sauvegarde ;
  • -
  • Mesures restrictives limitant l’accès physiques aux données à caractère personnel.
  • -
- Sous-traitants -
- https://www.ovhcloud.com/fr/personal-data-protection - , - ], - ]} - headers={["Partenaire", "Pays destinataire", "Traitement réalisé", "Garanties"]} - /> - - - Cookies et autres traceurs - - - Un cookie est un fichier déposé sur votre terminal lors de la visite d’un site. Il a pour but de collecter - des informations relatives à votre navigation et de vous adresser des services adaptés à votre terminal - (ordinateur, mobile ou tablette). -
-
- Le site ne dépose pas de cookies de mesure d’audience (nombre de visites, pages consultées). Néanmoins, nous - utilisons Plausible qui permet de suivre les tendances d’utilisation de notre site. L’outil ne permet pas - d’identifier les personnes, ni de tracer votre usage d’internet, dans ou en dehors du site. -
-
- Pour plus d’information à propos de Plausible : -
- - https://plausible.io/data-policy#first-thing-first-what-we-collect-and-what-we-use-it-for - {" "} - et https://plausible.io/privacy. -
- - - - ); -}; -export default PolitiqueDeConfidentialite; diff --git a/ui/app/(application)/politique-confidentialite/page.tsx b/ui/app/(application)/politique-confidentialite/page.tsx deleted file mode 100644 index 0d89126..0000000 --- a/ui/app/(application)/politique-confidentialite/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import Breadcrumb, { PAGES } from "../components/breadcrumb/Breadcrumb"; -import PolitiqueConfidentialite from "./components/PolitiqueConfidentialite"; - -const PolitiqueConfidentialitePage = () => { - return ( - <> - - - - ); -}; -export default PolitiqueConfidentialitePage; diff --git a/ui/app/(application)/sentry/page.tsx b/ui/app/(application)/sentry/page.tsx deleted file mode 100644 index 93d0ae8..0000000 --- a/ui/app/(application)/sentry/page.tsx +++ /dev/null @@ -1,86 +0,0 @@ -"use client"; - -import * as Sentry from "@sentry/nextjs"; -import Head from "next/head"; - -export default function Home() { - return ( -
- - Sentry Onboarding - - - -
-

- - - -

- -

Get started by sending us a sample error:

- - -

- Next, look for the error on the{" "} - Issues Page. -

-

- For more information, see{" "} - - https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -

-
-
- ); -} diff --git a/ui/app/sitemap.ts b/ui/app/sitemap.ts index cd6d51a..e94f337 100644 --- a/ui/app/sitemap.ts +++ b/ui/app/sitemap.ts @@ -16,7 +16,6 @@ export default function sitemap(): MetadataRoute.Sitemap { getSitemapItem(PAGES.accessibilite()), // getSitemapItem(PAGES.mentionsLegales()), // getSitemapItem(PAGES.cgu()), - // getSitemapItem(PAGES.donneesPersonnelles()), // getSitemapItem(PAGES.politiqueConfidentialite()), // getSitemapItem(PAGES.connexion()), // getSitemapItem(PAGES.motDePasseOublie()), diff --git a/ui/config.public.ts b/ui/config.public.ts index 2643540..86cac04 100644 --- a/ui/config.public.ts +++ b/ui/config.public.ts @@ -5,7 +5,7 @@ export interface PublicConfig { host: string; baseUrl: string; apiEndpoint: string; - env: "local" | "preview" | "recette" | "production"; + env: "local" | "recette" | "production"; version: string; productMeta: { productName: string; @@ -48,29 +48,6 @@ function getRecettePublicConfig(): PublicConfig { }; } -function getPreviewPublicConfig(): PublicConfig { - const version = getVersion(); - const matches = version.match(/^0\.0\.0-(\d+)$/); - - if (!matches) { - throw new Error(`getPreviewPublicConfig: invalid preview version ${version}`); - } - - const host = `${matches[1]}.contrat-preview.apprentissage.beta.gouv.fr`; - - return { - sentry: { - dsn: "https://3e7602056d8e0df1638f34fc89e7aee5@sentry.apprentissage.beta.gouv.fr/13", - }, - host, - baseUrl: `https://${host}`, - env: "preview", - apiEndpoint: `https://${host}/api`, - version: getVersion(), - productMeta: getProductMeta(), - }; -} - function getLocalPublicConfig(): PublicConfig { const host = "localhost"; return { @@ -117,7 +94,6 @@ function getEnv(): PublicConfig["env"] { switch (env) { case "production": case "recette": - case "preview": case "local": return env; default: @@ -131,8 +107,6 @@ function getPublicConfig(): PublicConfig { return getProductionPublicConfig(); case "recette": return getRecettePublicConfig(); - case "preview": - return getPreviewPublicConfig(); case "local": return getLocalPublicConfig(); } diff --git a/ui/context/AuthContext.tsx b/ui/context/AuthContext.tsx deleted file mode 100644 index 5ebb464..0000000 --- a/ui/context/AuthContext.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; -import { createContext, FC, PropsWithChildren, useContext, useState } from "react"; -import { IUserPublic } from "shared/models/user.model"; - -interface IAuthContext { - user?: IUserPublic; - setUser: (user?: IUserPublic) => void; -} - -export const AuthContext = createContext({ - user: undefined, - setUser: () => {}, -}); - -interface Props extends PropsWithChildren { - initialUser?: IUserPublic; -} - -export const AuthContextProvider: FC = ({ initialUser, children }) => { - const [user, setUser] = useState(initialUser); - - return {children}; -}; - -export const useAuth = () => useContext(AuthContext); diff --git a/ui/next.config.js b/ui/next.config.js index d1b6921..f80ad58 100644 --- a/ui/next.config.js +++ b/ui/next.config.js @@ -44,6 +44,26 @@ const nextConfig = { hideSourceMaps: false, widenClientFileUpload: true, }, + + async redirects() { + return [ + { + source: "/cgu", + destination: "https://cfas.apprentissage.beta.gouv.fr/cgu", + permanent: true, + }, + { + source: "/mentions-legales", + destination: "https://cfas.apprentissage.beta.gouv.fr/mentions-legales", + permanent: true, + }, + { + source: "/politique-confidentialite", + destination: "https://cfas.apprentissage.beta.gouv.fr/politique-de-confidentialite", + permanent: true, + }, + ]; + }, async headers() { return [ { diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 8f9ca23..71e9705 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -9,7 +9,6 @@ export default defineWorkspace([ root: "./server", include: ["./tests/**/*.test.ts", "./src/**/*.test.ts"], setupFiles: ["./tests/setup.ts"], - globalSetup: ["./server/tests/globalSetup.ts"], threads: true, }, }, diff --git a/yarn.lock b/yarn.lock index aae5074..c752ba1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,17 +22,6 @@ __metadata: languageName: node linkType: hard -"@asteasolutions/zod-to-openapi@npm:^6.2.0": - version: 6.3.0 - resolution: "@asteasolutions/zod-to-openapi@npm:6.3.0" - dependencies: - openapi3-ts: ^4.1.2 - peerDependencies: - zod: ^3.20.2 - checksum: 67cdfcb6b7867ee182907d6ff46ef6aadb1c57b7a8e094f7f219a5b104ac34a2b012a95801275b9afe220113fc74d7debf90c65e6e43a8f820d39fd0398a66cc - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.21.4": version: 7.23.4 resolution: "@babel/code-frame@npm:7.23.4" @@ -339,59 +328,6 @@ __metadata: languageName: node linkType: hard -"@cypress/chrome-recorder@npm:^2.3.1": - version: 2.3.1 - resolution: "@cypress/chrome-recorder@npm:2.3.1" - dependencies: - "@puppeteer/replay": ^2.10.2 - chalk: ^5.0.1 - execa: ^6.1.0 - globby: ^13.1.1 - inquirer: ^8.2.1 - is-git-clean: ^1.1.0 - meow: ^10.1.2 - bin: - chrome-recorder: bin/cypress-chrome-recorder.js - checksum: 807e4028a3a72e988eb5dbb9cb68aeafe8fee301ed293bb77a542625c90d8beac374568b4dcf2e19de8ef52a6e66973b786032c639463ff8ba016e26e5db7219 - languageName: node - linkType: hard - -"@cypress/request@npm:2.88.12": - version: 2.88.12 - resolution: "@cypress/request@npm:2.88.12" - dependencies: - aws-sign2: ~0.7.0 - aws4: ^1.8.0 - caseless: ~0.12.0 - combined-stream: ~1.0.6 - extend: ~3.0.2 - forever-agent: ~0.6.1 - form-data: ~2.3.2 - http-signature: ~1.3.6 - is-typedarray: ~1.0.0 - isstream: ~0.1.2 - json-stringify-safe: ~5.0.1 - mime-types: ~2.1.19 - performance-now: ^2.1.0 - qs: ~6.10.3 - safe-buffer: ^5.1.2 - tough-cookie: ^4.1.3 - tunnel-agent: ^0.6.0 - uuid: ^8.3.2 - checksum: 2c6fbf7f3127d41bffca8374beaa8cf95450495a8a077b00309ea9d94dd2a4da450a77fe038e8ad26c97cdd7c39b65c53c850f8338ce9bc2dbe23ce2e2b48329 - languageName: node - linkType: hard - -"@cypress/xvfb@npm:^1.2.4": - version: 1.2.4 - resolution: "@cypress/xvfb@npm:1.2.4" - dependencies: - debug: ^3.1.0 - lodash.once: ^4.1.1 - checksum: 7bdcdaeb1bb692ec9d9bf8ec52538aa0bead6764753f4a067a171a511807a43fab016f7285a56bef6a606c2467ff3f1365e1ad2d2d583b81beed849ee1573fd1 - languageName: node - linkType: hard - "@emotion/babel-plugin@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/babel-plugin@npm:11.11.0" @@ -1965,28 +1901,6 @@ __metadata: languageName: node linkType: hard -"@puppeteer/replay@npm:^2.10.2": - version: 2.13.4 - resolution: "@puppeteer/replay@npm:2.13.4" - dependencies: - cli-table3: 0.6.3 - colorette: 2.0.20 - yargs: 17.7.2 - peerDependencies: - lighthouse: ">=10.0.0" - puppeteer: ">=21.0.1" - peerDependenciesMeta: - lighthouse: - optional: true - puppeteer: - optional: true - bin: - replay: lib/cli.js - replay-extension-test: lib/extension-test.js - checksum: 9d1a60208abacee8763602c8f2603b07fc197bb43a6d3b42025818cd49f24d1e27a95a3c9aaec2d37cfdf4bc8538dbeb44b3f7af063e4639b34c7728b1ab9ee3 - languageName: node - linkType: hard - "@rollup/plugin-commonjs@npm:24.0.0": version: 24.0.0 resolution: "@rollup/plugin-commonjs@npm:24.0.0" @@ -2780,7 +2694,7 @@ __metadata: languageName: node linkType: hard -"@types/minimist@npm:^1.2.0, @types/minimist@npm:^1.2.2": +"@types/minimist@npm:^1.2.0": version: 1.2.5 resolution: "@types/minimist@npm:1.2.5" checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 @@ -2833,13 +2747,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^16.18.39": - version: 16.18.63 - resolution: "@types/node@npm:16.18.63" - checksum: 5600ad585e8bf68359cfbff965ebd6f04f22130232d057949c88840bf8acf6a05fbac343f69deac417439c47e8e5e396fdb049f575382f534bb98c0e8ac62a46 - languageName: node - linkType: hard - "@types/nodemailer-html-to-text@npm:^3.1.0": version: 3.1.3 resolution: "@types/nodemailer-html-to-text@npm:3.1.3" @@ -2932,20 +2839,6 @@ __metadata: languageName: node linkType: hard -"@types/sinonjs__fake-timers@npm:8.1.1": - version: 8.1.1 - resolution: "@types/sinonjs__fake-timers@npm:8.1.1" - checksum: ca09d54d47091d87020824a73f026300fa06b17cd9f2f9b9387f28b549364b141ef194ee28db762f6588de71d8febcd17f753163cb7ea116b8387c18e80ebd5c - languageName: node - linkType: hard - -"@types/sizzle@npm:^2.3.2": - version: 2.3.7 - resolution: "@types/sizzle@npm:2.3.7" - checksum: f5cd5b146d6ba3dd960ca2361126037af3f96799ac73297485d804d44ce2e5799eb95fa00888d24cd737ebfcb66691652145c5f6c873c4ab063a34a9caa04b37 - languageName: node - linkType: hard - "@types/unist@npm:*, @types/unist@npm:^3.0.0": version: 3.0.2 resolution: "@types/unist@npm:3.0.2" @@ -2976,25 +2869,6 @@ __metadata: languageName: node linkType: hard -"@types/whatwg-url@npm:^8.2.1": - version: 8.2.2 - resolution: "@types/whatwg-url@npm:8.2.2" - dependencies: - "@types/node": "*" - "@types/webidl-conversions": "*" - checksum: 5dc5afe078dfa1a8a266745586fa3db9baa8ce7cc904789211d1dca1d34d7f3dd17d0b7423c36bc9beab9d98aa99338f1fc60798c0af6cbb8356f20e20d9f243 - languageName: node - linkType: hard - -"@types/yauzl@npm:^2.9.1": - version: 2.10.3 - resolution: "@types/yauzl@npm:2.10.3" - dependencies: - "@types/node": "*" - checksum: 5ee966ea7bd6b2802f31ad4281c92c4c0b6dfa593c378a2582c58541fa113bec3d70eb0696b34ad95e8e6861a884cba6c3e351285816693ed176222f840a8c08 - languageName: node - linkType: hard - "@typescript-eslint/eslint-plugin@npm:^5.62.0": version: 5.62.0 resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" @@ -3452,15 +3326,6 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0": - version: 4.3.2 - resolution: "ansi-escapes@npm:4.3.2" - dependencies: - type-fest: ^0.21.3 - checksum: 93111c42189c0a6bed9cdb4d7f2829548e943827ee8479c74d6e0b22ee127b2a21d3f8b5ca57723b8ef78ce011fbfc2784350eb2bde3ccfccf2f575fa8489815 - languageName: node - linkType: hard - "ansi-escapes@npm:^5.0.0": version: 5.0.0 resolution: "ansi-escapes@npm:5.0.0" @@ -3556,13 +3421,6 @@ __metadata: languageName: node linkType: hard -"arch@npm:^2.2.0": - version: 2.2.0 - resolution: "arch@npm:2.2.0" - checksum: e21b7635029fe8e9cdd5a026f9a6c659103e63fff423834323cdf836a1bb240a72d0c39ca8c470f84643385cf581bd8eda2cad8bf493e27e54bd9783abe9101f - languageName: node - linkType: hard - "archy@npm:^1.0.0, archy@npm:~1.0.0": version: 1.0.0 resolution: "archy@npm:1.0.0" @@ -3630,13 +3488,6 @@ __metadata: languageName: node linkType: hard -"array-differ@npm:^1.0.0": - version: 1.0.0 - resolution: "array-differ@npm:1.0.0" - checksum: ac6060952c7cb0a534c06ea3c6c960432d605d905e9901afe386e841aadc6e102ed81e0e6abe5eb4b50dd43907fc6426f6012b5ca784ec7741a5b398690c0998 - languageName: node - linkType: hard - "array-ify@npm:^1.0.0": version: 1.0.0 resolution: "array-ify@npm:1.0.0" @@ -3657,15 +3508,6 @@ __metadata: languageName: node linkType: hard -"array-union@npm:^1.0.1": - version: 1.0.2 - resolution: "array-union@npm:1.0.2" - dependencies: - array-uniq: ^1.0.1 - checksum: 82cec6421b6e6766556c484835a6d476a873f1b71cace5ab2b4f1b15b1e3162dc4da0d16f7a2b04d4aec18146c6638fe8f661340b31ba8e469fd811a1b45dc8d - languageName: node - linkType: hard - "array-union@npm:^2.1.0": version: 2.1.0 resolution: "array-union@npm:2.1.0" @@ -3673,13 +3515,6 @@ __metadata: languageName: node linkType: hard -"array-uniq@npm:^1.0.1": - version: 1.0.3 - resolution: "array-uniq@npm:1.0.3" - checksum: 1625f06b093d8bf279b81adfec6e72951c0857d65b5e3f65f053fffe9f9dd61c2fc52cff57e38a4700817e7e3f01a4faa433d505ea9e33cdae4514c334e0bf9e - languageName: node - linkType: hard - "array.prototype.findlastindex@npm:^1.2.3": version: 1.2.3 resolution: "array.prototype.findlastindex@npm:1.2.3" @@ -3745,7 +3580,7 @@ __metadata: languageName: node linkType: hard -"arrify@npm:^1.0.0, arrify@npm:^1.0.1": +"arrify@npm:^1.0.1": version: 1.0.1 resolution: "arrify@npm:1.0.1" checksum: 745075dd4a4624ff0225c331dacb99be501a515d39bcb7c84d24660314a6ec28e68131b137e6f7e16318170842ce97538cd298fc4cd6b2cc798e0b957f2747e7 @@ -3782,14 +3617,7 @@ __metadata: languageName: node linkType: hard -"astral-regex@npm:^2.0.0": - version: 2.0.0 - resolution: "astral-regex@npm:2.0.0" - checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 - languageName: node - linkType: hard - -"async@npm:^3.2.0, async@npm:^3.2.3": +"async@npm:^3.2.3": version: 3.2.5 resolution: "async@npm:3.2.5" checksum: 5ec77f1312301dee02d62140a6b1f7ee0edd2a0f983b6fd2b0849b969f245225b990b47b8243e7b9ad16451a53e7f68e753700385b706198ced888beedba3af4 @@ -3812,13 +3640,6 @@ __metadata: languageName: node linkType: hard -"at-least-node@npm:^1.0.0": - version: 1.0.0 - resolution: "at-least-node@npm:1.0.0" - checksum: 463e2f8e43384f1afb54bc68485c436d7622acec08b6fad269b421cb1d29cebb5af751426793d0961ed243146fe4dc983402f6d5a51b720b277818dbf6f2e49e - languageName: node - linkType: hard - "atomic-sleep@npm:^1.0.0": version: 1.0.0 resolution: "atomic-sleep@npm:1.0.0" @@ -3989,31 +3810,6 @@ __metadata: languageName: node linkType: hard -"bl@npm:^4.1.0": - version: 4.1.0 - resolution: "bl@npm:4.1.0" - dependencies: - buffer: ^5.5.0 - inherits: ^2.0.4 - readable-stream: ^3.4.0 - checksum: 9e8521fa7e83aa9427c6f8ccdcba6e8167ef30cc9a22df26effcc5ab682ef91d2cbc23a239f945d099289e4bbcfae7a192e9c28c84c6202e710a0dfec3722662 - languageName: node - linkType: hard - -"blob-util@npm:^2.0.2": - version: 2.0.2 - resolution: "blob-util@npm:2.0.2" - checksum: d543e6b92e4ca715ca33c78e89a07a2290d43e5b2bc897d7ec588c5c7bbf59df93e45225ac0c9258aa6ce4320358990f99c9288f1c48280f8ec5d7a2e088d19b - languageName: node - linkType: hard - -"bluebird@npm:^3.7.2": - version: 3.7.2 - resolution: "bluebird@npm:3.7.2" - checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef - languageName: node - linkType: hard - "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -4056,7 +3852,7 @@ __metadata: languageName: node linkType: hard -"bson@npm:^5.4.0, bson@npm:^5.5.0": +"bson@npm:^5.4.0": version: 5.5.1 resolution: "bson@npm:5.5.1" checksum: f49730504e8362e2c8d1eb0c272e5e125392c41fb7196fc35ccbc39718ee62569a1d197bd2342c3334cd420073d3fd5dc7dea764a7f219dcd79e0ce473dd2772 @@ -4070,13 +3866,6 @@ __metadata: languageName: node linkType: hard -"buffer-crc32@npm:~0.2.3": - version: 0.2.13 - resolution: "buffer-crc32@npm:0.2.13" - checksum: 06252347ae6daca3453b94e4b2f1d3754a3b146a111d81c68924c22d91889a40623264e95e67955b1cb4a68cbedf317abeabb5140a9766ed248973096db5ce1c - languageName: node - linkType: hard - "buffer-equal-constant-time@npm:1.0.1": version: 1.0.1 resolution: "buffer-equal-constant-time@npm:1.0.1" @@ -4091,16 +3880,6 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.5.0, buffer@npm:^5.6.0": - version: 5.7.1 - resolution: "buffer@npm:5.7.1" - dependencies: - base64-js: ^1.3.1 - ieee754: ^1.1.13 - checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 - languageName: node - linkType: hard - "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -4279,13 +4058,6 @@ __metadata: languageName: node linkType: hard -"cachedir@npm:^2.3.0": - version: 2.4.0 - resolution: "cachedir@npm:2.4.0" - checksum: 43198514eaa61f65b5535ed29ad651f22836fba3868ed58a6a87731f05462f317d39098fa3ac778801c25455483c9b7f32a2fcad1f690a978947431f12a0f4d0 - languageName: node - linkType: hard - "call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": version: 1.0.5 resolution: "call-bind@npm:1.0.5" @@ -4325,18 +4097,6 @@ __metadata: languageName: node linkType: hard -"camelcase-keys@npm:^7.0.0": - version: 7.0.2 - resolution: "camelcase-keys@npm:7.0.2" - dependencies: - camelcase: ^6.3.0 - map-obj: ^4.1.0 - quick-lru: ^5.1.1 - type-fest: ^1.2.1 - checksum: b5821cc48dd00e8398a30c5d6547f06837ab44de123f1b3a603d0a03399722b2fc67a485a7e47106eb02ef543c3b50c5ebaabc1242cde4b63a267c3258d2365b - languageName: node - linkType: hard - "camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" @@ -4344,13 +4104,6 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.3.0": - version: 6.3.0 - resolution: "camelcase@npm:6.3.0" - checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d - languageName: node - linkType: hard - "caniuse-lite@npm:^1.0.30001406": version: 1.0.30001563 resolution: "caniuse-lite@npm:1.0.30001563" @@ -4416,7 +4169,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:5.3.0, chalk@npm:^5.0.1, chalk@npm:^5.2.0, chalk@npm:^5.3.0": +"chalk@npm:5.3.0, chalk@npm:^5.2.0, chalk@npm:^5.3.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80 @@ -4434,7 +4187,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.1": +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -4493,13 +4246,6 @@ __metadata: languageName: node linkType: hard -"chardet@npm:^0.7.0": - version: 0.7.0 - resolution: "chardet@npm:0.7.0" - checksum: 6fd5da1f5d18ff5712c1e0aed41da200d7c51c28f11b36ee3c7b483f3696dabc08927fc6b227735eb8f0e1215c9a8abd8154637f3eff8cada5959df7f58b024d - languageName: node - linkType: hard - "check-error@npm:^1.0.3": version: 1.0.3 resolution: "check-error@npm:1.0.3" @@ -4509,13 +4255,6 @@ __metadata: languageName: node linkType: hard -"check-more-types@npm:^2.24.0": - version: 2.24.0 - resolution: "check-more-types@npm:2.24.0" - checksum: b09080ec3404d20a4b0ead828994b2e5913236ef44ed3033a27062af0004cf7d2091fbde4b396bf13b7ce02fb018bc9960b48305e6ab2304cd82d73ed7a51ef4 - languageName: node - linkType: hard - "cheerio-select@npm:^2.1.0": version: 2.1.0 resolution: "cheerio-select@npm:2.1.0" @@ -4571,7 +4310,7 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^3.2.0, ci-info@npm:^3.6.1, ci-info@npm:^3.7.1, ci-info@npm:^3.8.0": +"ci-info@npm:^3.6.1, ci-info@npm:^3.7.1, ci-info@npm:^3.8.0": version: 3.9.0 resolution: "ci-info@npm:3.9.0" checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 @@ -4638,15 +4377,6 @@ __metadata: languageName: node linkType: hard -"cli-cursor@npm:^3.1.0": - version: 3.1.0 - resolution: "cli-cursor@npm:3.1.0" - dependencies: - restore-cursor: ^3.1.0 - checksum: 2692784c6cd2fd85cfdbd11f53aea73a463a6d64a77c3e098b2b4697a20443f430c220629e1ca3b195ea5ac4a97a74c2ee411f3807abf6df2b66211fec0c0a29 - languageName: node - linkType: hard - "cli-cursor@npm:^4.0.0": version: 4.0.0 resolution: "cli-cursor@npm:4.0.0" @@ -4656,14 +4386,7 @@ __metadata: languageName: node linkType: hard -"cli-spinners@npm:^2.5.0": - version: 2.9.1 - resolution: "cli-spinners@npm:2.9.1" - checksum: 1780618be58309c469205bc315db697934bac68bce78cd5dfd46248e507a533172d623c7348ecfd904734f597ce0a4e5538684843d2cfb7af485d4466699940c - languageName: node - linkType: hard - -"cli-table3@npm:0.6.3, cli-table3@npm:^0.6.1, cli-table3@npm:^0.6.3, cli-table3@npm:~0.6.1": +"cli-table3@npm:^0.6.1, cli-table3@npm:^0.6.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -4676,16 +4399,6 @@ __metadata: languageName: node linkType: hard -"cli-truncate@npm:^2.1.0": - version: 2.1.0 - resolution: "cli-truncate@npm:2.1.0" - dependencies: - slice-ansi: ^3.0.0 - string-width: ^4.2.0 - checksum: bf1e4e6195392dc718bf9cd71f317b6300dc4a9191d052f31046b8773230ece4fa09458813bf0e3455a5e68c0690d2ea2c197d14a8b85a7b5e01c97f4b5feb5d - languageName: node - linkType: hard - "cli-truncate@npm:^3.1.0": version: 3.1.0 resolution: "cli-truncate@npm:3.1.0" @@ -4696,13 +4409,6 @@ __metadata: languageName: node linkType: hard -"cli-width@npm:^3.0.0": - version: 3.0.0 - resolution: "cli-width@npm:3.0.0" - checksum: 4c94af3769367a70e11ed69aa6095f1c600c0ff510f3921ab4045af961820d57c0233acfa8b6396037391f31b4c397e1f614d234294f979ff61430a6c166c3f6 - languageName: node - linkType: hard - "client-only@npm:0.0.1": version: 0.0.1 resolution: "client-only@npm:0.0.1" @@ -4810,7 +4516,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:2.0.20, colorette@npm:^2.0.16, colorette@npm:^2.0.20, colorette@npm:^2.0.7": +"colorette@npm:^2.0.20, colorette@npm:^2.0.7": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d @@ -4871,7 +4577,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^6.1.0, commander@npm:^6.2.1": +"commander@npm:^6.1.0": version: 6.2.1 resolution: "commander@npm:6.2.1" checksum: d7090410c0de6bc5c67d3ca41c41760d6d268f3c799e530aafb73b7437d1826bbf0d2a3edac33f8b57cc9887b4a986dce307fa5557e109be40eadb7c43b21742 @@ -4899,13 +4605,6 @@ __metadata: languageName: node linkType: hard -"common-tags@npm:^1.8.0": - version: 1.8.2 - resolution: "common-tags@npm:1.8.2" - checksum: 767a6255a84bbc47df49a60ab583053bb29a7d9687066a18500a516188a062c4e4cd52de341f22de0b07062e699b1b8fe3cfa1cb55b241cb9301aeb4f45b4dff - languageName: node - linkType: hard - "commondir@npm:^1.0.1": version: 1.0.1 resolution: "commondir@npm:1.0.1" @@ -5152,16 +4851,6 @@ __metadata: languageName: node linkType: hard -"cross-spawn-async@npm:^2.1.1": - version: 2.2.5 - resolution: "cross-spawn-async@npm:2.2.5" - dependencies: - lru-cache: ^4.0.0 - which: ^1.2.8 - checksum: 6d9059a68a643d9a7506c0d7ca518a803a4293d62cbd3763bdb18cac0dd7bfa9b07d6705361a23c486c7b790e4a2fbfc3d63b93e21de52ad862794b12c6f055f - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -5244,59 +4933,6 @@ __metadata: languageName: node linkType: hard -"cypress@npm:^12.17.4": - version: 12.17.4 - resolution: "cypress@npm:12.17.4" - dependencies: - "@cypress/request": 2.88.12 - "@cypress/xvfb": ^1.2.4 - "@types/node": ^16.18.39 - "@types/sinonjs__fake-timers": 8.1.1 - "@types/sizzle": ^2.3.2 - arch: ^2.2.0 - blob-util: ^2.0.2 - bluebird: ^3.7.2 - buffer: ^5.6.0 - cachedir: ^2.3.0 - chalk: ^4.1.0 - check-more-types: ^2.24.0 - cli-cursor: ^3.1.0 - cli-table3: ~0.6.1 - commander: ^6.2.1 - common-tags: ^1.8.0 - dayjs: ^1.10.4 - debug: ^4.3.4 - enquirer: ^2.3.6 - eventemitter2: 6.4.7 - execa: 4.1.0 - executable: ^4.1.1 - extract-zip: 2.0.1 - figures: ^3.2.0 - fs-extra: ^9.1.0 - getos: ^3.2.1 - is-ci: ^3.0.0 - is-installed-globally: ~0.4.0 - lazy-ass: ^1.6.0 - listr2: ^3.8.3 - lodash: ^4.17.21 - log-symbols: ^4.0.0 - minimist: ^1.2.8 - ospath: ^1.2.2 - pretty-bytes: ^5.6.0 - process: ^0.11.10 - proxy-from-env: 1.0.0 - request-progress: ^3.0.0 - semver: ^7.5.3 - supports-color: ^8.1.1 - tmp: ~0.2.1 - untildify: ^4.0.0 - yauzl: ^2.10.0 - bin: - cypress: bin/cypress - checksum: c9c79f5493b23e9c8cfb92d45d50ea9d0fae54210dde203bfa794a79436faf60108d826fe9007a7d67fddf7919802ad8f006b7ae56c5c198c75d5bc85bbc851b - languageName: node - linkType: hard - "damerau-levenshtein@npm:^1.0.8": version: 1.0.8 resolution: "damerau-levenshtein@npm:1.0.8" @@ -5343,13 +4979,6 @@ __metadata: languageName: node linkType: hard -"dayjs@npm:^1.10.4": - version: 1.11.10 - resolution: "dayjs@npm:1.11.10" - checksum: a6b5a3813b8884f5cd557e2e6b7fa569f4c5d0c97aca9558e38534af4f2d60daafd3ff8c2000fed3435cfcec9e805bcebd99f90130c6d1c5ef524084ced588c4 - languageName: node - linkType: hard - "debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -5362,7 +4991,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:^3.1.0, debug@npm:^3.2.7": +"debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" dependencies: @@ -5388,13 +5017,6 @@ __metadata: languageName: node linkType: hard -"decamelize@npm:^5.0.0": - version: 5.0.1 - resolution: "decamelize@npm:5.0.1" - checksum: 7c3b1ed4b3e60e7fbc00a35fb248298527c1cdfe603e41dfcf05e6c4a8cb9efbee60630deb677ed428908fb4e74e322966c687a094d1478ddc9c3a74e9dc7140 - languageName: node - linkType: hard - "decode-named-character-reference@npm:^1.0.0": version: 1.0.2 resolution: "decode-named-character-reference@npm:1.0.2" @@ -5824,16 +5446,6 @@ __metadata: languageName: node linkType: hard -"enquirer@npm:^2.3.6": - version: 2.4.1 - resolution: "enquirer@npm:2.4.1" - dependencies: - ansi-colors: ^4.1.1 - strip-ansi: ^6.0.1 - checksum: f080f11a74209647dbf347a7c6a83c8a47ae1ebf1e75073a808bc1088eb780aa54075bfecd1bcdb3e3c724520edb8e6ee05da031529436b421b71066fcc48cb5 - languageName: node - linkType: hard - "entities@npm:^2.0.0": version: 2.2.0 resolution: "entities@npm:2.2.0" @@ -6257,17 +5869,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-cypress@npm:^2.14.0": - version: 2.15.1 - resolution: "eslint-plugin-cypress@npm:2.15.1" - dependencies: - globals: ^13.20.0 - peerDependencies: - eslint: ">= 3.2.1" - checksum: 3e66fa9a943fff52eaf3758250a63c2a0f8ffd60c50572beaf3688b33a55fbf0060d18ef32bc26abb57aef070517db827c22fd3d607582861d464970f95e550e - languageName: node - linkType: hard - "eslint-plugin-es-x@npm:^7.1.0": version: 7.3.0 resolution: "eslint-plugin-es-x@npm:7.3.0" @@ -6658,13 +6259,6 @@ __metadata: languageName: node linkType: hard -"eventemitter2@npm:6.4.7": - version: 6.4.7 - resolution: "eventemitter2@npm:6.4.7" - checksum: 1b36a77e139d6965ebf3a36c01fa00c089ae6b80faa1911e52888f40b3a7057b36a2cc45dcd1ad87cda3798fe7b97a0aabcbb8175a8b96092a23bb7d0f039e66 - languageName: node - linkType: hard - "eventemitter3@npm:^5.0.1": version: 5.0.1 resolution: "eventemitter3@npm:5.0.1" @@ -6686,23 +6280,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:4.1.0": - version: 4.1.0 - resolution: "execa@npm:4.1.0" - dependencies: - cross-spawn: ^7.0.0 - get-stream: ^5.0.0 - human-signals: ^1.1.1 - is-stream: ^2.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^4.0.0 - onetime: ^5.1.0 - signal-exit: ^3.0.2 - strip-final-newline: ^2.0.0 - checksum: e30d298934d9c52f90f3847704fd8224e849a081ab2b517bbc02f5f7732c24e56a21f14cb96a08256deffeb2d12b2b7cb7e2b014a12fb36f8d3357e06417ed55 - languageName: node - linkType: hard - "execa@npm:7.2.0, execa@npm:^7.0.0": version: 7.2.0 resolution: "execa@npm:7.2.0" @@ -6720,20 +6297,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^0.4.0": - version: 0.4.0 - resolution: "execa@npm:0.4.0" - dependencies: - cross-spawn-async: ^2.1.1 - is-stream: ^1.1.0 - npm-run-path: ^1.0.0 - object-assign: ^4.0.1 - path-key: ^1.0.0 - strip-eof: ^1.0.0 - checksum: aa78c841cbb11b279127f2155e243f7fd766369f8a928ccab9aaa88687ee765e60f7de626ed4056c540ea6c4d7347819a4ae4426076a481edc47585dce989f8e - languageName: node - linkType: hard - "execa@npm:^5.0.0": version: 5.1.1 resolution: "execa@npm:5.1.1" @@ -6751,23 +6314,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^6.1.0": - version: 6.1.0 - resolution: "execa@npm:6.1.0" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.1 - human-signals: ^3.0.1 - is-stream: ^3.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^5.1.0 - onetime: ^6.0.0 - signal-exit: ^3.0.7 - strip-final-newline: ^3.0.0 - checksum: 1a4af799839134f5c72eb63d525b87304c1114a63aa71676c91d57ccef2e26f2f53e14c11384ab11c4ec479be1efa83d11c8190e00040355c2c5c3364327fa8e - languageName: node - linkType: hard - "execa@npm:^8.0.0": version: 8.0.1 resolution: "execa@npm:8.0.1" @@ -6785,15 +6331,6 @@ __metadata: languageName: node linkType: hard -"executable@npm:^4.1.1": - version: 4.1.1 - resolution: "executable@npm:4.1.1" - dependencies: - pify: ^2.2.0 - checksum: f01927ce59bccec804e171bf859a26e362c1f50aa9ebc69f7cafdcce3859d29d4b6267fd47237c18b0a1830614bd3f0ee14b7380d9bad18a4e7af9b5f0b6984f - languageName: node - linkType: hard - "exenv@npm:^1.2.0": version: 1.2.2 resolution: "exenv@npm:1.2.2" @@ -6815,34 +6352,6 @@ __metadata: languageName: node linkType: hard -"external-editor@npm:^3.0.3": - version: 3.1.0 - resolution: "external-editor@npm:3.1.0" - dependencies: - chardet: ^0.7.0 - iconv-lite: ^0.4.24 - tmp: ^0.0.33 - checksum: 1c2a616a73f1b3435ce04030261bed0e22d4737e14b090bb48e58865da92529c9f2b05b893de650738d55e692d071819b45e1669259b2b354bc3154d27a698c7 - languageName: node - linkType: hard - -"extract-zip@npm:2.0.1": - version: 2.0.1 - resolution: "extract-zip@npm:2.0.1" - dependencies: - "@types/yauzl": ^2.9.1 - debug: ^4.1.1 - get-stream: ^5.1.0 - yauzl: ^2.10.0 - dependenciesMeta: - "@types/yauzl": - optional: true - bin: - extract-zip: cli.js - checksum: 8cbda9debdd6d6980819cc69734d874ddd71051c9fe5bde1ef307ebcedfe949ba57b004894b585f758b7c9eeeea0e3d87f2dda89b7d25320459c2c9643ebb635 - languageName: node - linkType: hard - "extsprintf@npm:1.3.0": version: 1.3.0 resolution: "extsprintf@npm:1.3.0" @@ -6892,7 +6401,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.1, fast-glob@npm:^3.3.2": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -7044,15 +6553,6 @@ __metadata: languageName: node linkType: hard -"fd-slicer@npm:~1.1.0": - version: 1.1.0 - resolution: "fd-slicer@npm:1.1.0" - dependencies: - pend: ~1.2.0 - checksum: c8585fd5713f4476eb8261150900d2cb7f6ff2d87f8feb306ccc8a1122efd152f1783bdb2b8dc891395744583436bfd8081d8e63ece0ec8687eeefea394d4ff2 - languageName: node - linkType: hard - "figures@npm:^2.0.0": version: 2.0.0 resolution: "figures@npm:2.0.0" @@ -7062,15 +6562,6 @@ __metadata: languageName: node linkType: hard -"figures@npm:^3.0.0, figures@npm:^3.2.0": - version: 3.2.0 - resolution: "figures@npm:3.2.0" - dependencies: - escape-string-regexp: ^1.0.5 - checksum: 85a6ad29e9aca80b49b817e7c89ecc4716ff14e3779d9835af554db91bac41c0f289c418923519392a1e582b4d10482ad282021330cd045bb7b80c84152f2a2b - languageName: node - linkType: hard - "figures@npm:^5.0.0": version: 5.0.0 resolution: "figures@npm:5.0.0" @@ -7315,18 +6806,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^9.1.0": - version: 9.1.0 - resolution: "fs-extra@npm:9.1.0" - dependencies: - at-least-node: ^1.0.0 - graceful-fs: ^4.2.0 - jsonfile: ^6.0.1 - universalify: ^2.0.0 - checksum: ba71ba32e0faa74ab931b7a0031d1523c66a73e225de7426e275e238e312d07313d2da2d33e34a52aa406c8763ade5712eb3ec9ba4d9edce652bcacdc29e6b20 - languageName: node - linkType: hard - "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -7455,7 +6934,7 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^5.0.0, get-stream@npm:^5.1.0": +"get-stream@npm:^5.1.0": version: 5.2.0 resolution: "get-stream@npm:5.2.0" dependencies: @@ -7504,15 +6983,6 @@ __metadata: languageName: node linkType: hard -"getos@npm:^3.2.1": - version: 3.2.1 - resolution: "getos@npm:3.2.1" - dependencies: - async: ^3.2.0 - checksum: 42fd78a66d47cebd3e09de5566cc0044e034b08f4a000a310dbd89a77b02c65d8f4002554bfa495ea5bdc4fa9d515f5ac785a7cc474ba45383cc697f865eeaf1 - languageName: node - linkType: hard - "getpass@npm:^0.1.1": version: 0.1.7 resolution: "getpass@npm:0.1.7" @@ -7668,15 +7138,6 @@ __metadata: languageName: node linkType: hard -"global-dirs@npm:^3.0.0": - version: 3.0.1 - resolution: "global-dirs@npm:3.0.1" - dependencies: - ini: 2.0.0 - checksum: 70147b80261601fd40ac02a104581432325c1c47329706acd773f3a6ce99bb36d1d996038c85ccacd482ad22258ec233c586b6a91535b1a116b89663d49d6438 - languageName: node - linkType: hard - "global@npm:4.4.0": version: 4.4.0 resolution: "global@npm:4.4.0" @@ -7687,7 +7148,7 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.19.0, globals@npm:^13.20.0": +"globals@npm:^13.19.0": version: 13.23.0 resolution: "globals@npm:13.23.0" dependencies: @@ -7719,19 +7180,6 @@ __metadata: languageName: node linkType: hard -"globby@npm:^13.1.1": - version: 13.2.2 - resolution: "globby@npm:13.2.2" - dependencies: - dir-glob: ^3.0.1 - fast-glob: ^3.3.0 - ignore: ^5.2.4 - merge2: ^1.4.1 - slash: ^4.0.0 - checksum: f3d84ced58a901b4fcc29c846983108c426631fe47e94872868b65565495f7bee7b3defd68923bd480582771fd4bbe819217803a164a618ad76f1d22f666f41e - languageName: node - linkType: hard - "globby@npm:^14.0.0": version: 14.0.0 resolution: "globby@npm:14.0.0" @@ -8176,17 +7624,6 @@ __metadata: languageName: node linkType: hard -"http-signature@npm:~1.3.6": - version: 1.3.6 - resolution: "http-signature@npm:1.3.6" - dependencies: - assert-plus: ^1.0.0 - jsprim: ^2.0.2 - sshpk: ^1.14.1 - checksum: 10be2af4764e71fee0281392937050201ee576ac755c543f570d6d87134ce5e858663fe999a7adb3e4e368e1e356d0d7fec6b9542295b875726ff615188e7a0c - languageName: node - linkType: hard - "http2-wrapper@npm:^1.0.0-beta.5.2": version: 1.0.3 resolution: "http2-wrapper@npm:1.0.3" @@ -8217,13 +7654,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^1.1.1": - version: 1.1.1 - resolution: "human-signals@npm:1.1.1" - checksum: d587647c9e8ec24e02821b6be7de5a0fc37f591f6c4e319b3054b43fd4c35a70a94c46fc74d8c1a43c47fde157d23acd7421f375e1c1365b09a16835b8300205 - languageName: node - linkType: hard - "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -8231,13 +7661,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^3.0.1": - version: 3.0.1 - resolution: "human-signals@npm:3.0.1" - checksum: f252a7769c8094a5c9dc6772816bdb417b188820b04c8b42d0fc468e03a0ba905b1dd07afabe9385cc83504af1ccc2b985cd1e4aeeeb8e0029896c5af2e6f354 - languageName: node - linkType: hard - "human-signals@npm:^4.3.0": version: 4.3.1 resolution: "human-signals@npm:4.3.1" @@ -8277,15 +7700,6 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: ">= 2.1.2 < 3" - checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 - languageName: node - linkType: hard - "iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -8295,7 +7709,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": +"ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e @@ -8396,20 +7810,13 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.1, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:~2.0.1, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 languageName: node linkType: hard -"ini@npm:2.0.0": - version: 2.0.0 - resolution: "ini@npm:2.0.0" - checksum: e7aadc5fb2e4aefc666d74ee2160c073995a4061556b1b5b4241ecb19ad609243b9cceafe91bae49c219519394bbd31512516cb22a3b1ca6e66d869e0447e84e - languageName: node - linkType: hard - "ini@npm:^1.3.4, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" @@ -8456,29 +7863,6 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:^8.2.1": - version: 8.2.6 - resolution: "inquirer@npm:8.2.6" - dependencies: - ansi-escapes: ^4.2.1 - chalk: ^4.1.1 - cli-cursor: ^3.1.0 - cli-width: ^3.0.0 - external-editor: ^3.0.3 - figures: ^3.0.0 - lodash: ^4.17.21 - mute-stream: 0.0.8 - ora: ^5.4.1 - run-async: ^2.4.0 - rxjs: ^7.5.5 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - through: ^2.3.6 - wrap-ansi: ^6.0.1 - checksum: 387ffb0a513559cc7414eb42c57556a60e302f820d6960e89d376d092e257a919961cd485a1b4de693dbb5c0de8bc58320bfd6247dfd827a873aa82a4215a240 - languageName: node - linkType: hard - "internal-slot@npm:^1.0.5": version: 1.0.6 resolution: "internal-slot@npm:1.0.6" @@ -8642,17 +8026,6 @@ __metadata: languageName: node linkType: hard -"is-ci@npm:^3.0.0": - version: 3.0.1 - resolution: "is-ci@npm:3.0.1" - dependencies: - ci-info: ^3.2.0 - bin: - is-ci: bin.js - checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e - languageName: node - linkType: hard - "is-cidr@npm:^4.0.2": version: 4.0.2 resolution: "is-cidr@npm:4.0.2" @@ -8733,17 +8106,6 @@ __metadata: languageName: node linkType: hard -"is-git-clean@npm:^1.1.0": - version: 1.1.0 - resolution: "is-git-clean@npm:1.1.0" - dependencies: - execa: ^0.4.0 - is-obj: ^1.0.1 - multimatch: ^2.1.0 - checksum: aa89b03f97f02e9dbf5990ad002b33f75bdb83abd0626e60e76d03f62981ad2500b33e7b9eea9f2fdf861ae818ee40663d052902f4c7c0897067463d36072259 - languageName: node - linkType: hard - "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -8767,23 +8129,6 @@ __metadata: languageName: node linkType: hard -"is-installed-globally@npm:~0.4.0": - version: 0.4.0 - resolution: "is-installed-globally@npm:0.4.0" - dependencies: - global-dirs: ^3.0.0 - is-path-inside: ^3.0.2 - checksum: 3359840d5982d22e9b350034237b2cda2a12bac1b48a721912e1ab8e0631dd07d45a2797a120b7b87552759a65ba03e819f1bd63f2d7ab8657ec0b44ee0bf399 - languageName: node - linkType: hard - -"is-interactive@npm:^1.0.0": - version: 1.0.0 - resolution: "is-interactive@npm:1.0.0" - checksum: 824808776e2d468b2916cdd6c16acacebce060d844c35ca6d82267da692e92c3a16fdba624c50b54a63f38bdc4016055b6f443ce57d7147240de4f8cdabaf6f9 - languageName: node - linkType: hard - "is-lambda@npm:^1.0.1": version: 1.0.1 resolution: "is-lambda@npm:1.0.1" @@ -8821,13 +8166,6 @@ __metadata: languageName: node linkType: hard -"is-obj@npm:^1.0.1": - version: 1.0.1 - resolution: "is-obj@npm:1.0.1" - checksum: 3ccf0efdea12951e0b9c784e2b00e77e87b2f8bd30b42a498548a8afcc11b3287342a2030c308e473e93a7a19c9ea7854c99a8832a476591c727df2a9c79796c - languageName: node - linkType: hard - "is-obj@npm:^2.0.0": version: 2.0.0 resolution: "is-obj@npm:2.0.0" @@ -8835,7 +8173,7 @@ __metadata: languageName: node linkType: hard -"is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3": +"is-path-inside@npm:^3.0.3": version: 3.0.3 resolution: "is-path-inside@npm:3.0.3" checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 @@ -8912,13 +8250,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^1.1.0": - version: 1.1.0 - resolution: "is-stream@npm:1.1.0" - checksum: 063c6bec9d5647aa6d42108d4c59723d2bd4ae42135a2d4db6eadbd49b7ea05b750fd69d279e5c7c45cf9da753ad2c00d8978be354d65aa9f6bb434969c6a2ae - languageName: node - linkType: hard - "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -8985,13 +8316,6 @@ __metadata: languageName: node linkType: hard -"is-unicode-supported@npm:^0.1.0": - version: 0.1.0 - resolution: "is-unicode-supported@npm:0.1.0" - checksum: a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 - languageName: node - linkType: hard - "is-unicode-supported@npm:^1.2.0": version: 1.3.0 resolution: "is-unicode-supported@npm:1.3.0" @@ -9305,7 +8629,7 @@ __metadata: languageName: node linkType: hard -"json-schema@npm:0.4.0, json-schema@npm:^0.4.0": +"json-schema@npm:0.4.0": version: 0.4.0 resolution: "json-schema@npm:0.4.0" checksum: 66389434c3469e698da0df2e7ac5a3281bcff75e797a5c127db7c5b56270e01ae13d9afa3c03344f76e32e81678337a8c912bdbb75101c62e487dc3778461d72 @@ -9410,18 +8734,6 @@ __metadata: languageName: node linkType: hard -"jsprim@npm:^2.0.2": - version: 2.0.2 - resolution: "jsprim@npm:2.0.2" - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - checksum: d175f6b1991e160cb0aa39bc857da780e035611986b5492f32395411879fdaf4e513d98677f08f7352dac93a16b66b8361c674b86a3fa406e2e7af6b26321838 - languageName: node - linkType: hard - "jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": version: 3.3.5 resolution: "jsx-ast-utils@npm:3.3.5" @@ -9527,13 +8839,6 @@ __metadata: languageName: node linkType: hard -"lazy-ass@npm:^1.6.0": - version: 1.6.0 - resolution: "lazy-ass@npm:1.6.0" - checksum: 5a3ebb17915b03452320804466345382a6c25ac782ec4874fecdb2385793896cd459be2f187dc7def8899180c32ee0ab9a1aa7fe52193ac3ff3fe29bb0591729 - languageName: node - linkType: hard - "levn@npm:^0.4.1": version: 0.4.1 resolution: "levn@npm:0.4.1" @@ -9773,27 +9078,6 @@ __metadata: languageName: node linkType: hard -"listr2@npm:^3.8.3": - version: 3.14.0 - resolution: "listr2@npm:3.14.0" - dependencies: - cli-truncate: ^2.1.0 - colorette: ^2.0.16 - log-update: ^4.0.0 - p-map: ^4.0.0 - rfdc: ^1.3.0 - rxjs: ^7.5.1 - through: ^2.3.8 - wrap-ansi: ^7.0.0 - peerDependencies: - enquirer: ">= 2.3.0 < 3" - peerDependenciesMeta: - enquirer: - optional: true - checksum: fdb8b2d6bdf5df9371ebd5082bee46c6d0ca3d1e5f2b11fbb5a127839855d5f3da9d4968fce94f0a5ec67cac2459766abbb1faeef621065ebb1829b11ef9476d - languageName: node - linkType: hard - "load-json-file@npm:^4.0.0": version: 4.0.0 resolution: "load-json-file@npm:4.0.0" @@ -9996,7 +9280,7 @@ __metadata: languageName: node linkType: hard -"lodash.once@npm:^4.0.0, lodash.once@npm:^4.1.1": +"lodash.once@npm:^4.0.0": version: 4.1.1 resolution: "lodash.once@npm:4.1.1" checksum: d768fa9f9b4e1dc6453be99b753906f58990e0c45e7b2ca5a3b40a33111e5d17f6edf2f768786e2716af90a8e78f8f91431ab8435f761fef00f9b0c256f6d245 @@ -10066,28 +9350,6 @@ __metadata: languageName: node linkType: hard -"log-symbols@npm:^4.0.0, log-symbols@npm:^4.1.0": - version: 4.1.0 - resolution: "log-symbols@npm:4.1.0" - dependencies: - chalk: ^4.1.0 - is-unicode-supported: ^0.1.0 - checksum: fce1497b3135a0198803f9f07464165e9eb83ed02ceb2273930a6f8a508951178d8cf4f0378e9d28300a2ed2bc49050995d2bd5f53ab716bb15ac84d58c6ef74 - languageName: node - linkType: hard - -"log-update@npm:^4.0.0": - version: 4.0.0 - resolution: "log-update@npm:4.0.0" - dependencies: - ansi-escapes: ^4.3.0 - cli-cursor: ^3.1.0 - slice-ansi: ^4.0.0 - wrap-ansi: ^6.2.0 - checksum: ae2f85bbabc1906034154fb7d4c4477c79b3e703d22d78adee8b3862fa913942772e7fa11713e3d96fb46de4e3cabefbf5d0a544344f03b58d3c4bff52aa9eb2 - languageName: node - linkType: hard - "log-update@npm:^5.0.1": version: 5.0.1 resolution: "log-update@npm:5.0.1" @@ -10156,16 +9418,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^4.0.0": - version: 4.1.5 - resolution: "lru-cache@npm:4.1.5" - dependencies: - pseudomap: ^1.0.2 - yallist: ^2.1.2 - checksum: 4bb4b58a36cd7dc4dcec74cbe6a8f766a38b7426f1ff59d4cf7d82a2aa9b9565cd1cb98f6ff60ce5cd174524868d7bc9b7b1c294371851356066ca9ac4cf135a - languageName: node - linkType: hard - "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -10182,13 +9434,6 @@ __metadata: languageName: node linkType: hard -"luhn@npm:^2.4.1": - version: 2.4.1 - resolution: "luhn@npm:2.4.1" - checksum: 7abe856cef12c3ef720953280486693c15594190950da75264f4376d84112566b090ac5aa7b92c2c169f325a40c30362a1331c8ce1714565109fb79b39b27c03 - languageName: node - linkType: hard - "luxon@npm:^3.2.1": version: 3.4.4 resolution: "luxon@npm:3.4.4" @@ -10326,7 +9571,7 @@ __metadata: languageName: node linkType: hard -"map-obj@npm:^4.0.0, map-obj@npm:^4.1.0": +"map-obj@npm:^4.0.0": version: 4.3.0 resolution: "map-obj@npm:4.3.0" checksum: fbc554934d1a27a1910e842bc87b177b1a556609dd803747c85ece420692380827c6ae94a95cce4407c054fa0964be3bf8226f7f2cb2e9eeee432c7c1985684e @@ -10616,26 +9861,6 @@ __metadata: languageName: node linkType: hard -"meow@npm:^10.1.2": - version: 10.1.5 - resolution: "meow@npm:10.1.5" - dependencies: - "@types/minimist": ^1.2.2 - camelcase-keys: ^7.0.0 - decamelize: ^5.0.0 - decamelize-keys: ^1.1.0 - hard-rejection: ^2.1.0 - minimist-options: 4.1.0 - normalize-package-data: ^3.0.2 - read-pkg-up: ^8.0.0 - redent: ^4.0.0 - trim-newlines: ^4.0.2 - type-fest: ^1.2.2 - yargs-parser: ^20.2.9 - checksum: dd5f0caa4af18517813547dc66741dcbf52c4c23def5062578d39b11189fd9457aee5c1f2263a5cd6592a465023df8357e8ac876b685b64dbcf545e3f66c23a7 - languageName: node - linkType: hard - "meow@npm:^12.0.1": version: 12.1.1 resolution: "meow@npm:12.1.1" @@ -11108,14 +10333,14 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": +"min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 languageName: node linkType: hard -"minimatch@npm:2 || 3, minimatch@npm:^3.0.0, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:2 || 3, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -11162,7 +10387,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8, minimist@npm:~1.2.5": +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:~1.2.5": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -11718,19 +10943,16 @@ __metadata: dependencies: "@commitlint/cli": ^17.7.1 "@commitlint/config-conventional": ^17.7.0 - "@cypress/chrome-recorder": ^2.3.1 "@semantic-release/changelog": ^6.0.3 "@semantic-release/exec": ^6.0.3 "@typescript-eslint/eslint-plugin": ^5.62.0 "@typescript-eslint/parser": ^5.62.0 "@vitest/coverage-v8": ^0.34.2 commander: ^10.0.1 - cypress: ^12.17.4 dotenv: ^16.4.5 eslint: ^8.47.0 eslint-config-next: ^13.4.17 eslint-import-resolver-typescript: ^3.6.0 - eslint-plugin-cypress: ^2.14.0 eslint-plugin-import: ^2.28.0 eslint-plugin-jsx-a11y: ^6.7.1 eslint-plugin-mocha: ^10.1.0 @@ -11776,16 +10998,6 @@ __metadata: languageName: node linkType: hard -"mongodb-connection-string-url@npm:^2.6.0": - version: 2.6.0 - resolution: "mongodb-connection-string-url@npm:2.6.0" - dependencies: - "@types/whatwg-url": ^8.2.1 - whatwg-url: ^11.0.0 - checksum: 1d662f0ecfe96f7a400f625c244b2e52914c98f3562ee7d19941127578b5f8237624433bdcea285a654041b945b518803512989690c74548aec5860c5541c605 - languageName: node - linkType: hard - "mongodb-connection-string-url@npm:^3.0.0": version: 3.0.0 resolution: "mongodb-connection-string-url@npm:3.0.0" @@ -11796,38 +11008,6 @@ __metadata: languageName: node linkType: hard -"mongodb@npm:^5.7.0": - version: 5.9.1 - resolution: "mongodb@npm:5.9.1" - dependencies: - "@mongodb-js/saslprep": ^1.1.0 - bson: ^5.5.0 - mongodb-connection-string-url: ^2.6.0 - socks: ^2.7.1 - peerDependencies: - "@aws-sdk/credential-providers": ^3.188.0 - "@mongodb-js/zstd": ^1.0.0 - kerberos: ^1.0.0 || ^2.0.0 - mongodb-client-encryption: ">=2.3.0 <3" - snappy: ^7.2.2 - dependenciesMeta: - "@mongodb-js/saslprep": - optional: true - peerDependenciesMeta: - "@aws-sdk/credential-providers": - optional: true - "@mongodb-js/zstd": - optional: true - kerberos: - optional: true - mongodb-client-encryption: - optional: true - snappy: - optional: true - checksum: a827937120cd7eecafc0ad5657b40536774f0b09582a9363db0a192149ba20eae80a33fccf573f5ce69a20aca6759c40b4961d9d1d4de2a350c543030055e0f6 - languageName: node - linkType: hard - "mongodb@npm:^6.1.0": version: 6.3.0 resolution: "mongodb@npm:6.3.0" @@ -11876,18 +11056,6 @@ __metadata: languageName: node linkType: hard -"multimatch@npm:^2.1.0": - version: 2.1.0 - resolution: "multimatch@npm:2.1.0" - dependencies: - array-differ: ^1.0.0 - array-union: ^1.0.1 - arrify: ^1.0.0 - minimatch: ^3.0.0 - checksum: 19259848ec28e5b3ee150ef3ac4a7d3d4afd0c285556e58f349e393b6b4cb6d99abe14415aa2183f4e6309c42d4d3cf941da7ad1b088753024c41ad8b280b03b - languageName: node - linkType: hard - "multipipe@npm:^1.0.2": version: 1.0.2 resolution: "multipipe@npm:1.0.2" @@ -11898,13 +11066,6 @@ __metadata: languageName: node linkType: hard -"mute-stream@npm:0.0.8": - version: 0.0.8 - resolution: "mute-stream@npm:0.0.8" - checksum: ff48d251fc3f827e5b1206cda0ffdaec885e56057ee86a3155e1951bc940fd5f33531774b1cc8414d7668c10a8907f863f6561875ee6e8768931a62121a531a1 - languageName: node - linkType: hard - "mute-stream@npm:~1.0.0": version: 1.0.0 resolution: "mute-stream@npm:1.0.0" @@ -12229,7 +11390,7 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^3.0.0, normalize-package-data@npm:^3.0.2": +"normalize-package-data@npm:^3.0.0": version: 3.0.3 resolution: "normalize-package-data@npm:3.0.3" dependencies: @@ -12415,16 +11576,7 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^1.0.0": - version: 1.0.0 - resolution: "npm-run-path@npm:1.0.0" - dependencies: - path-key: ^1.0.0 - checksum: ffabf15b6e4cb6f511a49cb9c824db67cd13198938988d18362fb62e793650b10d5e87695016625d3bed06fb9ab6a3b359265d97910d8971c8fdca845d3aaadd - languageName: node - linkType: hard - -"npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": +"npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" dependencies: @@ -12720,15 +11872,6 @@ __metadata: languageName: node linkType: hard -"openapi3-ts@npm:^4.1.2": - version: 4.1.2 - resolution: "openapi3-ts@npm:4.1.2" - dependencies: - yaml: ^2.2.2 - checksum: 019a66f4195966bf58ee29f913b91e39975616458fdb40a15507a3b3e338eacfc882def0dda1a5001edf962e382ed6f46c8a0d40684adcccb868960267df30d9 - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.3 resolution: "optionator@npm:0.9.3" @@ -12743,37 +11886,6 @@ __metadata: languageName: node linkType: hard -"ora@npm:^5.4.1": - version: 5.4.1 - resolution: "ora@npm:5.4.1" - dependencies: - bl: ^4.1.0 - chalk: ^4.1.0 - cli-cursor: ^3.1.0 - cli-spinners: ^2.5.0 - is-interactive: ^1.0.0 - is-unicode-supported: ^0.1.0 - log-symbols: ^4.1.0 - strip-ansi: ^6.0.0 - wcwidth: ^1.0.1 - checksum: 28d476ee6c1049d68368c0dc922e7225e3b5600c3ede88fade8052837f9ed342625fdaa84a6209302587c8ddd9b664f71f0759833cbdb3a4cf81344057e63c63 - languageName: node - linkType: hard - -"os-tmpdir@npm:~1.0.2": - version: 1.0.2 - resolution: "os-tmpdir@npm:1.0.2" - checksum: 5666560f7b9f10182548bf7013883265be33620b1c1b4a4d405c25be2636f970c5488ff3e6c48de75b55d02bde037249fe5dbfbb4c0fb7714953d56aed062e6d - languageName: node - linkType: hard - -"ospath@npm:^1.2.2": - version: 1.2.2 - resolution: "ospath@npm:1.2.2" - checksum: 505f48a4f4f1c557d6c656ec985707726e3714721680139be037613e903aa8c8fa4ddd8d1342006f9b2dc0065e6e20f8b7bea2ee05354f31257044790367b347 - languageName: node - linkType: hard - "p-cancelable@npm:^2.0.0": version: 2.1.1 resolution: "p-cancelable@npm:2.1.1" @@ -13122,13 +12234,6 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^1.0.0": - version: 1.0.0 - resolution: "path-key@npm:1.0.0" - checksum: 41c4aa248d3b2e4f98b98c753b3721da7a25060cdce1ac95944ae19c71b7d85702b790558763c0371bab46269f40aa8b5ec4a3353954d0c05c8231c41dae9cf0 - languageName: node - linkType: hard - "path-key@npm:^3.0.0, path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -13212,13 +12317,6 @@ __metadata: languageName: node linkType: hard -"pend@npm:~1.2.0": - version: 1.2.0 - resolution: "pend@npm:1.2.0" - checksum: 6c72f5243303d9c60bd98e6446ba7d30ae29e3d56fdb6fae8767e8ba6386f33ee284c97efe3230a0d0217e2b1723b8ab490b1bbf34fcbb2180dbc8a9de47850d - languageName: node - linkType: hard - "performance-now@npm:^2.1.0": version: 2.1.0 resolution: "performance-now@npm:2.1.0" @@ -13249,13 +12347,6 @@ __metadata: languageName: node linkType: hard -"pify@npm:^2.2.0": - version: 2.3.0 - resolution: "pify@npm:2.3.0" - checksum: 9503aaeaf4577acc58642ad1d25c45c6d90288596238fb68f82811c08104c800e5a7870398e9f015d82b44ecbcbef3dc3d4251a1cbb582f6e5959fe09884b2ba - languageName: node - linkType: hard - "pify@npm:^3.0.0": version: 3.0.0 resolution: "pify@npm:3.0.0" @@ -13408,13 +12499,6 @@ __metadata: languageName: node linkType: hard -"pretty-bytes@npm:^5.6.0": - version: 5.6.0 - resolution: "pretty-bytes@npm:5.6.0" - checksum: 9c082500d1e93434b5b291bd651662936b8bd6204ec9fa17d563116a192d6d86b98f6d328526b4e8d783c07d5499e2614a807520249692da9ec81564b2f439cd - languageName: node - linkType: hard - "pretty-format@npm:^29.5.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" @@ -13557,13 +12641,6 @@ __metadata: languageName: node linkType: hard -"proxy-from-env@npm:1.0.0": - version: 1.0.0 - resolution: "proxy-from-env@npm:1.0.0" - checksum: 292e28d1de0c315958d71d8315eb546dd3cd8c8cbc2dab7c54eeb9f5c17f421771964ad0b5e1f77011bab2305bdae42e1757ce33bdb1ccc3e87732322a8efcf1 - languageName: node - linkType: hard - "proxy-from-env@npm:^1.1.0": version: 1.1.0 resolution: "proxy-from-env@npm:1.1.0" @@ -13571,14 +12648,7 @@ __metadata: languageName: node linkType: hard -"pseudomap@npm:^1.0.2": - version: 1.0.2 - resolution: "pseudomap@npm:1.0.2" - checksum: 856c0aae0ff2ad60881168334448e898ad7a0e45fe7386d114b150084254c01e200c957cf378378025df4e052c7890c5bd933939b0e0d2ecfcc1dc2f0b2991f5 - languageName: node - linkType: hard - -"psl@npm:^1.1.28, psl@npm:^1.1.33": +"psl@npm:^1.1.28": version: 1.9.0 resolution: "psl@npm:1.9.0" checksum: 20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d @@ -13611,15 +12681,6 @@ __metadata: languageName: node linkType: hard -"qs@npm:~6.10.3": - version: 6.10.4 - resolution: "qs@npm:6.10.4" - dependencies: - side-channel: ^1.0.4 - checksum: 31e4fedd759d01eae52dde6692abab175f9af3e639993c5caaa513a2a3607b34d8058d3ae52ceeccf37c3025f22ed5e90e9ddd6c2537e19c0562ddd10dc5b1eb - languageName: node - linkType: hard - "qs@npm:~6.5.2": version: 6.5.3 resolution: "qs@npm:6.5.3" @@ -13638,13 +12699,6 @@ __metadata: languageName: node linkType: hard -"querystringify@npm:^2.1.1": - version: 2.2.0 - resolution: "querystringify@npm:2.2.0" - checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 - languageName: node - linkType: hard - "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -14018,17 +13072,6 @@ __metadata: languageName: node linkType: hard -"read-pkg-up@npm:^8.0.0": - version: 8.0.0 - resolution: "read-pkg-up@npm:8.0.0" - dependencies: - find-up: ^5.0.0 - read-pkg: ^6.0.0 - type-fest: ^1.0.1 - checksum: fe4c80401656b40b408884457fffb5a8015c03b1018cfd8e48f8d82a5e9023e24963603aeb2755608d964593e046c15b34d29b07d35af9c7aa478be81805209c - languageName: node - linkType: hard - "read-pkg@npm:^5.2.0": version: 5.2.0 resolution: "read-pkg@npm:5.2.0" @@ -14041,18 +13084,6 @@ __metadata: languageName: node linkType: hard -"read-pkg@npm:^6.0.0": - version: 6.0.0 - resolution: "read-pkg@npm:6.0.0" - dependencies: - "@types/normalize-package-data": ^2.4.0 - normalize-package-data: ^3.0.2 - parse-json: ^5.2.0 - type-fest: ^1.0.1 - checksum: 0cebdff381128e923815c643074a87011070e5fc352bee575d327d6485da3317fab6d802a7b03deeb0be7be8d3ad1640397b3d5d2f044452caf4e8d1736bf94f - languageName: node - linkType: hard - "read-pkg@npm:^8.0.0, read-pkg@npm:^8.1.0": version: 8.1.0 resolution: "read-pkg@npm:8.1.0" @@ -14074,7 +13105,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": +"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -14167,16 +13198,6 @@ __metadata: languageName: node linkType: hard -"redent@npm:^4.0.0": - version: 4.0.0 - resolution: "redent@npm:4.0.0" - dependencies: - indent-string: ^5.0.0 - strip-indent: ^4.0.0 - checksum: 6944e7b1d8f3fd28c2515f5c605b9f7f0ea0f4edddf41890bbbdd4d9ee35abb7540c3b278f03ff827bd278bb6ff4a5bd8692ca406b748c5c1c3ce7355e9fbf8f - languageName: node - linkType: hard - "redeyed@npm:~2.1.0": version: 2.1.1 resolution: "redeyed@npm:2.1.1" @@ -14301,15 +13322,6 @@ __metadata: languageName: node linkType: hard -"request-progress@npm:^3.0.0": - version: 3.0.0 - resolution: "request-progress@npm:3.0.0" - dependencies: - throttleit: ^1.0.0 - checksum: 6ea1761dcc8a8b7b5894afd478c0286aa31bd69438d7050294bd4fd0d0b3e09b5cde417d38deef9c49809039c337d8744e4bb49d8632b0c3e4ffa5e8a687e0fd - languageName: node - linkType: hard - "request@npm:^2.88.2": version: 2.88.2 resolution: "request@npm:2.88.2" @@ -14352,13 +13364,6 @@ __metadata: languageName: node linkType: hard -"requires-port@npm:^1.0.0": - version: 1.0.0 - resolution: "requires-port@npm:1.0.0" - checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff - languageName: node - linkType: hard - "reselect@npm:^4.1.8": version: 4.1.8 resolution: "reselect@npm:4.1.8" @@ -14471,16 +13476,6 @@ __metadata: languageName: node linkType: hard -"restore-cursor@npm:^3.1.0": - version: 3.1.0 - resolution: "restore-cursor@npm:3.1.0" - dependencies: - onetime: ^5.1.0 - signal-exit: ^3.0.2 - checksum: f877dd8741796b909f2a82454ec111afb84eb45890eb49ac947d87991379406b3b83ff9673a46012fca0d7844bb989f45cc5b788254cf1a39b6b5a9659de0630 - languageName: node - linkType: hard - "restore-cursor@npm:^4.0.0": version: 4.0.0 resolution: "restore-cursor@npm:4.0.0" @@ -14519,7 +13514,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": +"rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -14628,13 +13623,6 @@ __metadata: languageName: node linkType: hard -"run-async@npm:^2.4.0": - version: 2.4.1 - resolution: "run-async@npm:2.4.1" - checksum: a2c88aa15df176f091a2878eb840e68d0bdee319d8d97bbb89112223259cebecb94bc0defd735662b83c2f7a30bed8cddb7d1674eb48ae7322dc602b22d03797 - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -14644,15 +13632,6 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.5.1, rxjs@npm:^7.5.5": - version: 7.8.1 - resolution: "rxjs@npm:7.8.1" - dependencies: - tslib: ^2.1.0 - checksum: de4b53db1063e618ec2eca0f7965d9137cabe98cf6be9272efe6c86b47c17b987383df8574861bcced18ebd590764125a901d5506082be84a8b8e364bf05f119 - languageName: node - linkType: hard - "safe-array-concat@npm:^1.0.1": version: 1.0.1 resolution: "safe-array-concat@npm:1.0.1" @@ -14713,7 +13692,7 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": +"safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 @@ -14910,7 +13889,6 @@ __metadata: lodash-es: ^4.17.21 migrate-mongo: ^10.0.0 mjml: ^4.14.1 - mongodb: ^5.7.0 nock: ^13.3.3 nodemailer: ^6.9.4 nodemailer-html-to-text: ^3.2.0 @@ -14923,7 +13901,6 @@ __metadata: typescript: ^5.1.6 vitest: ^0.34.6 zod: ^3.22.4 - zod-mongodb-schema: ^1.0.0 languageName: unknown linkType: soft @@ -14982,17 +13959,12 @@ __metadata: version: 0.0.0-use.local resolution: "shared@workspace:shared" dependencies: - "@asteasolutions/zod-to-openapi": ^6.2.0 bson: ^5.4.0 lodash-es: ^4.17.21 - luhn: ^2.4.1 - mongodb: ^5.7.0 - openapi3-ts: ^4.1.2 react: 18.2.0 type-fest: ^4.2.0 typescript: ^5.1.6 zod: ^3.22.1 - zod-to-json-schema: 3.21.4 languageName: unknown linkType: soft @@ -15092,13 +14064,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^4.0.0": - version: 4.0.0 - resolution: "slash@npm:4.0.0" - checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d - languageName: node - linkType: hard - "slash@npm:^5.1.0": version: 5.1.0 resolution: "slash@npm:5.1.0" @@ -15106,28 +14071,6 @@ __metadata: languageName: node linkType: hard -"slice-ansi@npm:^3.0.0": - version: 3.0.0 - resolution: "slice-ansi@npm:3.0.0" - dependencies: - ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 5ec6d022d12e016347e9e3e98a7eb2a592213a43a65f1b61b74d2c78288da0aded781f665807a9f3876b9daa9ad94f64f77d7633a0458876c3a4fdc4eb223f24 - languageName: node - linkType: hard - -"slice-ansi@npm:^4.0.0": - version: 4.0.0 - resolution: "slice-ansi@npm:4.0.0" - dependencies: - ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 - languageName: node - linkType: hard - "slice-ansi@npm:^5.0.0": version: 5.0.0 resolution: "slice-ansi@npm:5.0.0" @@ -15328,7 +14271,7 @@ __metadata: languageName: node linkType: hard -"sshpk@npm:^1.14.1, sshpk@npm:^1.7.0": +"sshpk@npm:^1.7.0": version: 1.18.0 resolution: "sshpk@npm:1.18.0" dependencies: @@ -15597,13 +14540,6 @@ __metadata: languageName: node linkType: hard -"strip-eof@npm:^1.0.0": - version: 1.0.0 - resolution: "strip-eof@npm:1.0.0" - checksum: 40bc8ddd7e072f8ba0c2d6d05267b4e0a4800898c3435b5fb5f5a21e6e47dfaff18467e7aa0d1844bb5d6274c3097246595841fbfeb317e541974ee992cac506 - languageName: node - linkType: hard - "strip-final-newline@npm:^2.0.0": version: 2.0.0 resolution: "strip-final-newline@npm:2.0.0" @@ -15627,15 +14563,6 @@ __metadata: languageName: node linkType: hard -"strip-indent@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-indent@npm:4.0.0" - dependencies: - min-indent: ^1.0.1 - checksum: 06cbcd93da721c46bc13caeb1c00af93a9b18146a1c95927672d2decab6a25ad83662772417cea9317a2507fb143253ecc23c4415b64f5828cef9b638a744598 - languageName: node - linkType: hard - "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -15734,15 +14661,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^8.1.1": - version: 8.1.1 - resolution: "supports-color@npm:8.1.1" - dependencies: - has-flag: ^4.0.0 - checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 - languageName: node - linkType: hard - "supports-color@npm:^9.4.0": version: 9.4.0 resolution: "supports-color@npm:9.4.0" @@ -15880,13 +14798,6 @@ __metadata: languageName: node linkType: hard -"throttleit@npm:^1.0.0": - version: 1.0.1 - resolution: "throttleit@npm:1.0.1" - checksum: 32e0b12ca5810cd34dfce0408c7cb658dfd039848a073466eaac667ce6e846cafa53ac518e4b01dc6f34e6652b66fd29a5c6b666718ec5086ef328a9d029dc75 - languageName: node - linkType: hard - "through2@npm:^4.0.0": version: 4.0.2 resolution: "through2@npm:4.0.2" @@ -15916,7 +14827,7 @@ __metadata: languageName: node linkType: hard -"through@npm:2, through@npm:>=2.2.7 <3, through@npm:^2.3.6, through@npm:^2.3.8": +"through@npm:2, through@npm:>=2.2.7 <3, through@npm:^2.3.8": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd @@ -15972,24 +14883,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.0.33": - version: 0.0.33 - resolution: "tmp@npm:0.0.33" - dependencies: - os-tmpdir: ~1.0.2 - checksum: 902d7aceb74453ea02abbf58c203f4a8fc1cead89b60b31e354f74ed5b3fb09ea817f94fb310f884a5d16987dd9fa5a735412a7c2dd088dd3d415aa819ae3a28 - languageName: node - linkType: hard - -"tmp@npm:~0.2.1": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: ^3.0.0 - checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e - languageName: node - linkType: hard - "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -16034,18 +14927,6 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.1.3": - version: 4.1.3 - resolution: "tough-cookie@npm:4.1.3" - dependencies: - psl: ^1.1.33 - punycode: ^2.1.1 - universalify: ^0.2.0 - url-parse: ^1.5.3 - checksum: c9226afff36492a52118432611af083d1d8493a53ff41ec4ea48e5b583aec744b989e4280bcf476c910ec1525a89a4a0f1cae81c08b18fb2ec3a9b3a72b91dcc - languageName: node - linkType: hard - "tough-cookie@npm:~2.5.0": version: 2.5.0 resolution: "tough-cookie@npm:2.5.0" @@ -16065,15 +14946,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^3.0.0": - version: 3.0.0 - resolution: "tr46@npm:3.0.0" - dependencies: - punycode: ^2.1.1 - checksum: 44c3cc6767fb800490e6e9fd64fd49041aa4e49e1f6a012b34a75de739cc9ed3a6405296072c1df8b6389ae139c5e7c6496f659cfe13a04a4bff3a1422981270 - languageName: node - linkType: hard - "tr46@npm:^4.1.1": version: 4.1.1 resolution: "tr46@npm:4.1.1" @@ -16127,13 +14999,6 @@ __metadata: languageName: node linkType: hard -"trim-newlines@npm:^4.0.2": - version: 4.1.1 - resolution: "trim-newlines@npm:4.1.1" - checksum: 5b09f8e329e8f33c1111ef26906332ba7ba7248cde3e26fc054bb3d69f2858bf5feedca9559c572ff91f33e52977c28e0d41c387df6a02a633cbb8c2d8238627 - languageName: node - linkType: hard - "trough@npm:^1.0.0": version: 1.0.5 resolution: "trough@npm:1.0.5" @@ -16360,13 +15225,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.21.3": - version: 0.21.3 - resolution: "type-fest@npm:0.21.3" - checksum: e6b32a3b3877f04339bae01c193b273c62ba7bfc9e325b8703c4ee1b32dc8fe4ef5dfa54bf78265e069f7667d058e360ae0f37be5af9f153b22382cd55a9afe0 - languageName: node - linkType: hard - "type-fest@npm:^0.6.0": version: 0.6.0 resolution: "type-fest@npm:0.6.0" @@ -16388,7 +15246,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^1.0.1, type-fest@npm:^1.0.2, type-fest@npm:^1.2.1, type-fest@npm:^1.2.2": +"type-fest@npm:^1.0.1, type-fest@npm:^1.0.2": version: 1.4.0 resolution: "type-fest@npm:1.4.0" checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 @@ -16756,13 +15614,6 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^0.2.0": - version: 0.2.0 - resolution: "universalify@npm:0.2.0" - checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 - languageName: node - linkType: hard - "universalify@npm:^2.0.0": version: 2.0.1 resolution: "universalify@npm:2.0.1" @@ -16770,13 +15621,6 @@ __metadata: languageName: node linkType: hard -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: 39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 - languageName: node - linkType: hard - "upper-case@npm:^1.1.1": version: 1.1.3 resolution: "upper-case@npm:1.1.3" @@ -16800,16 +15644,6 @@ __metadata: languageName: node linkType: hard -"url-parse@npm:^1.5.3": - version: 1.5.10 - resolution: "url-parse@npm:1.5.10" - dependencies: - querystringify: ^2.1.1 - requires-port: ^1.0.0 - checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf - languageName: node - linkType: hard - "use-sync-external-store@npm:^1.2.0": version: 1.2.0 resolution: "use-sync-external-store@npm:1.2.0" @@ -16835,15 +15669,6 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^8.3.2": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" - bin: - uuid: dist/bin/uuid - checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df - languageName: node - linkType: hard - "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1" @@ -17100,7 +15925,7 @@ __metadata: languageName: node linkType: hard -"wcwidth@npm:^1.0.0, wcwidth@npm:^1.0.1": +"wcwidth@npm:^1.0.0": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" dependencies: @@ -17151,16 +15976,6 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^11.0.0": - version: 11.0.0 - resolution: "whatwg-url@npm:11.0.0" - dependencies: - tr46: ^3.0.0 - webidl-conversions: ^7.0.0 - checksum: ed4826aaa57e66bb3488a4b25c9cd476c46ba96052747388b5801f137dd740b73fde91ad207d96baf9f17fbcc80fc1a477ad65181b5eb5fa718d27c69501d7af - languageName: node - linkType: hard - "whatwg-url@npm:^13.0.0": version: 13.0.0 resolution: "whatwg-url@npm:13.0.0" @@ -17250,17 +16065,6 @@ __metadata: languageName: node linkType: hard -"which@npm:^1.2.8": - version: 1.3.1 - resolution: "which@npm:1.3.1" - dependencies: - isexe: ^2.0.0 - bin: - which: ./bin/which - checksum: f2e185c6242244b8426c9df1510e86629192d93c1a986a7d2a591f2c24869e7ffd03d6dac07ca863b2e4c06f59a4cc9916c585b72ee9fa1aa609d0124df15e04 - languageName: node - linkType: hard - "which@npm:^2.0.1, which@npm:^2.0.2": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -17333,17 +16137,6 @@ __metadata: languageName: node linkType: hard -"wrap-ansi@npm:^6.0.1, wrap-ansi@npm:^6.2.0": - version: 6.2.0 - resolution: "wrap-ansi@npm:6.2.0" - dependencies: - ansi-styles: ^4.0.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a - languageName: node - linkType: hard - "wrap-ansi@npm:^8.0.1, wrap-ansi@npm:^8.1.0": version: 8.1.0 resolution: "wrap-ansi@npm:8.1.0" @@ -17395,13 +16188,6 @@ __metadata: languageName: node linkType: hard -"yallist@npm:^2.1.2": - version: 2.1.2 - resolution: "yallist@npm:2.1.2" - checksum: 9ba99409209f485b6fcb970330908a6d41fa1c933f75e08250316cce19383179a6b70a7e0721b89672ebb6199cc377bf3e432f55100da6a7d6e11902b0a642cb - languageName: node - linkType: hard - "yallist@npm:^4.0.0": version: 4.0.0 resolution: "yallist@npm:4.0.0" @@ -17430,7 +16216,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3, yargs-parser@npm:^20.2.9": +"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 @@ -17444,21 +16230,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.5.1": - version: 17.7.2 - resolution: "yargs@npm:17.7.2" - dependencies: - cliui: ^8.0.1 - escalade: ^3.1.1 - get-caller-file: ^2.0.5 - require-directory: ^2.1.1 - string-width: ^4.2.3 - y18n: ^5.0.5 - yargs-parser: ^21.1.1 - checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a - languageName: node - linkType: hard - "yargs@npm:^16.1.0": version: 16.2.0 resolution: "yargs@npm:16.2.0" @@ -17474,13 +16245,18 @@ __metadata: languageName: node linkType: hard -"yauzl@npm:^2.10.0": - version: 2.10.0 - resolution: "yauzl@npm:2.10.0" +"yargs@npm:^17.0.0, yargs@npm:^17.5.1": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" dependencies: - buffer-crc32: ~0.2.3 - fd-slicer: ~1.1.0 - checksum: 7f21fe0bbad6e2cb130044a5d1d0d5a0e5bf3d8d4f8c4e6ee12163ce798fee3de7388d22a7a0907f563ac5f9d40f8699a223d3d5c1718da90b0156da6904022b + cliui: ^8.0.1 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.3 + y18n: ^5.0.5 + yargs-parser: ^21.1.1 + checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a languageName: node linkType: hard @@ -17517,29 +16293,7 @@ __metadata: languageName: node linkType: hard -"zod-mongodb-schema@npm:^1.0.0": - version: 1.0.0 - resolution: "zod-mongodb-schema@npm:1.0.0" - dependencies: - json-schema: ^0.4.0 - zod-to-json-schema: ^3.21.4 - peerDependencies: - mongodb: ^6.2.0 - zod: ^3.22.4 - checksum: 6c78ff5e8aee2590b03154676c8e20b34bbd34975e805918875cc46fedb89f1b6690137ea3ea23057909fd38ab35ea73967cca875ad30eee5d3ce1baaaeb6f43 - languageName: node - linkType: hard - -"zod-to-json-schema@npm:3.21.4": - version: 3.21.4 - resolution: "zod-to-json-schema@npm:3.21.4" - peerDependencies: - zod: ^3.21.4 - checksum: 899c1f461fb6547c0b08a265c82040c250be9b88d3f408f2f3ff77a418fdfad7549077e589d418fccb312c1f6d555c3c7217b199cc9072762e1fab20716dd2a6 - languageName: node - linkType: hard - -"zod-to-json-schema@npm:^3.17.1, zod-to-json-schema@npm:^3.21.4": +"zod-to-json-schema@npm:^3.17.1": version: 3.22.0 resolution: "zod-to-json-schema@npm:3.22.0" peerDependencies: From f763653497e33a625efb32cbfc4970bd406abba4 Mon Sep 17 00:00:00 2001 From: Moroine Bentefrit Date: Tue, 12 Nov 2024 13:38:33 +0100 Subject: [PATCH 2/2] chore: remove deadcode --- package.json | 1 - server/package.json | 23 - server/src/common/apis/entreprise.ts | 2 +- .../common/controllers/geo/geoController.ts | 17 +- server/src/common/services/sentry/sentry.ts | 23 - server/src/common/utils/apiUtils.ts | 2 +- server/src/common/utils/getStaticFilePath.ts | 2 +- server/src/modules/actions/cerfa.actions.ts | 6 +- .../server/middlewares/errorMiddleware.ts | 2 +- server/src/modules/server/server.ts | 2 +- server/src/modules/server/utils/geoUtils.ts | 42 - shared/constants/categoriesJuridiques.ts | 2 +- shared/constants/diplomes.ts | 2 +- shared/constants/idcc.ts | 2 +- shared/constants/index.ts | 2 - shared/constants/opcos.ts | 2 +- shared/constants/pays.ts | 387 ---- shared/constants/regex.ts | 36 - shared/constants/territoires.ts | 1586 ------------- shared/constants/typeVoie.ts | 47 - .../domains/common/indiceRepetitionOptions.ts | 18 - shared/helpers/cerfa/types/cerfa.types.ts | 13 +- shared/helpers/common.ts | 1 - shared/package.json | 4 +- shared/routes/common.routes.ts | 19 - shared/security/permissions.ts | 36 - shared/utils/assertUnreachable.ts | 3 - shared/utils/index.ts | 1 - .../cerfa/components/CheckEmptyFields.tsx | 2 +- .../contrat/domain/buildRemuneration.ts | 667 ------ .../controls/apprentiDateNaissance.control.ts | 2 +- .../controls/apprentiNationalite.control.ts | 2 +- .../cerfa/controls/apprentiNir.control.ts | 2 +- .../cerfa/controls/apprentiSexe.control.ts | 2 +- .../cerfa/controls/common/nir.control.ts | 2 +- .../cerfa/controls/employeurSiret.control.ts | 2 +- .../cerfa/controls/utils/api.utils.ts | 7 - .../controls/utils/createCopyOrRestoreRule.ts | 35 - .../(application)/cerfa/utils/cerfa.utils.ts | 2 +- .../(application)/cerfa/utils/cerfaSchema.ts | 2 +- .../(application)/cerfa/utils/form.utils.ts | 37 +- ui/components/SearchBar.tsx | 12 - ui/components/ThemeProvider.tsx | 4 - ui/components/form/ToggleSwitchInput.tsx | 27 - ui/components/form/input/Input.tsx | 89 - ui/components/form/input/MaskInput.tsx | 2 +- ui/components/form/input/PhoneInput.tsx | 2 +- ui/components/infoDetails/InfoDetails.tsx | 48 - ui/components/table/Table.tsx | 25 - ui/components/toast/Toast.tsx | 39 - ui/config.public.ts | 2 +- ui/icons/NotFound copy.tsx | 416 ---- ui/package.json | 4 - ui/utils/api.utils.ts | 49 +- ui/utils/date.utils.ts | 13 - ui/utils/query.utils.ts | 29 - yarn.lock | 2058 +---------------- 57 files changed, 146 insertions(+), 5720 deletions(-) delete mode 100644 shared/constants/index.ts delete mode 100644 shared/constants/pays.ts delete mode 100644 shared/constants/regex.ts delete mode 100644 shared/constants/territoires.ts delete mode 100644 shared/constants/typeVoie.ts delete mode 100644 shared/helpers/cerfa/domains/common/indiceRepetitionOptions.ts delete mode 100644 shared/helpers/common.ts delete mode 100644 shared/security/permissions.ts delete mode 100644 shared/utils/assertUnreachable.ts delete mode 100644 shared/utils/index.ts delete mode 100644 ui/app/(application)/cerfa/components/blocks/contrat/domain/buildRemuneration.ts delete mode 100644 ui/components/SearchBar.tsx delete mode 100644 ui/components/ThemeProvider.tsx delete mode 100644 ui/components/form/ToggleSwitchInput.tsx delete mode 100644 ui/components/form/input/Input.tsx delete mode 100644 ui/components/infoDetails/InfoDetails.tsx delete mode 100644 ui/components/table/Table.tsx delete mode 100644 ui/components/toast/Toast.tsx delete mode 100644 ui/icons/NotFound copy.tsx diff --git a/package.json b/package.json index 6d24fed..f5cc92a 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "dependencies": { "dotenv": "^16.4.5", "eslint-plugin-react": "^7.32.2", - "global": "4.4.0", "husky": "^8.0.3" }, "scripts": { diff --git a/server/package.json b/server/package.json index 05dad27..2b80523 100644 --- a/server/package.json +++ b/server/package.json @@ -17,41 +17,25 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@fastify/auth": "^4.4.0", "@fastify/cookie": "^9.1.0", "@fastify/cors": "^8.4.1", "@fastify/multipart": "^8.0.0", - "@fastify/swagger": "^8.12.0", - "@fastify/swagger-ui": "^1.10.1", "@hapi/boom": "^10.0.1", "@immobiliarelabs/fastify-sentry": "^7.1.1", "@sentry/integrations": "^7.77.0", "@sentry/node": "^7.77.0", - "@sentry/tracing": "^7.77.0", "adm-zip": "^0.5.12", "axios": "^1.5.1", "axios-cache-interceptor": "^1.3.2", - "axios-retry": "^3.8.0", "bunyan": "^1.8.15", "bunyan-prettystream": "^0.1.3", "commander": "^10.0.1", - "cron-parser": "^4.9.0", - "csv-parse": "^5.4.0", - "date-fns": "^2.30.0", - "ejs": "^3.1.9", "env-var": "^7.3.1", "fastify": "^4.21.0", "fastify-type-provider-zod": "^1.1.9", - "job-processor": "^1.4.7", - "jsonwebtoken": "^9.0.1", "lil-http-terminator": "^1.2.3", "lodash-es": "^4.17.21", - "migrate-mongo": "^10.0.0", - "mjml": "^4.14.1", - "nodemailer": "^6.9.4", - "nodemailer-html-to-text": "^3.2.0", "pdf-lib": "^1.17.1", - "pino-pretty": "^10.2.3", "query-string": "^9.0.0", "rate-limiter-flexible": "^2.4.2", "shared": "workspace:*", @@ -61,15 +45,8 @@ "@types/adm-zip": "^0.5.5", "@types/bunyan": "^1.8.8", "@types/bunyan-prettystream": "^0.1.32", - "@types/ejs": "^3.1.2", - "@types/jsonwebtoken": "^9.0.2", "@types/lodash-es": "^4.17.8", - "@types/migrate-mongo": "^10.0.0", - "@types/mjml": "^4.7.1", - "@types/nodemailer": "^6.4.9", - "@types/nodemailer-html-to-text": "^3.1.0", "dotenv": "^16.4.5", - "nock": "^13.3.3", "tsup": "^7.2.0", "typescript": "^5.1.6", "vitest": "^0.34.6" diff --git a/server/src/common/apis/entreprise.ts b/server/src/common/apis/entreprise.ts index f6c2593..df26e3a 100644 --- a/server/src/common/apis/entreprise.ts +++ b/server/src/common/apis/entreprise.ts @@ -28,7 +28,7 @@ const apiParams = { non_diffusables: true, }; -export const getEntreprisePart = (endpoint: string) => { +const getEntreprisePart = (endpoint: string) => { return apiEntrepriseClient(async (client) => { try { logger.debug(`[Entreprise API] Fetching entreprise part ${endpoint}...`); diff --git a/server/src/common/controllers/geo/geoController.ts b/server/src/common/controllers/geo/geoController.ts index 1a019e5..1d5bf91 100644 --- a/server/src/common/controllers/geo/geoController.ts +++ b/server/src/common/controllers/geo/geoController.ts @@ -1,12 +1,6 @@ import { departements } from "shared/constants/departements"; -import { - Adresse, - Coordinates, - getAddressFromGeoCoordinates, - getGeoCoordinateFromAdresse, - getMunicipality, -} from "./geoAdresseData"; +import { Adresse, getGeoCoordinateFromAdresse, getMunicipality } from "./geoAdresseData"; export const findCode = async (code: string, codeInsee: string | null) => { try { @@ -74,15 +68,6 @@ export const findGeoCoordinateFromAdresse = async ({ }; }; -export const findAddressFromGeoCoordinates = async ({ latitude, longitude }: Coordinates) => { - const { address, results_count } = await getAddressFromGeoCoordinates({ latitude, longitude }); - return { - info: `Ok`, - value: address, - count: results_count, - }; -}; - export const isValidCodePostal = (codePostal: string) => { return /^[0-9]{5}$/g.test(codePostal); }; diff --git a/server/src/common/services/sentry/sentry.ts b/server/src/common/services/sentry/sentry.ts index d8db2e0..4d0d022 100644 --- a/server/src/common/services/sentry/sentry.ts +++ b/server/src/common/services/sentry/sentry.ts @@ -48,26 +48,3 @@ export function initSentryFastify(app: Server) { // @ts-expect-error app.register(fastifySentryPlugin, { options, ...getOptions() }); } - -function getTransation() { - return Sentry.getCurrentHub()?.getScope()?.getSpan(); -} - -export function startSentryPerfRecording( - category: string, - operation: string, - data: { - [key: string]: unknown; - } = {} -): () => void { - const childTransaction = - getTransation()?.startChild({ - op: category, - description: operation, - data, - }) ?? null; - - return () => { - childTransaction?.finish(); - }; -} diff --git a/server/src/common/utils/apiUtils.ts b/server/src/common/utils/apiUtils.ts index 6c6a956..02bc96a 100644 --- a/server/src/common/utils/apiUtils.ts +++ b/server/src/common/utils/apiUtils.ts @@ -13,7 +13,7 @@ interface ApiRateLimiterOptions { client: AxiosInstance | AxiosCacheInstance; } -export type ApiRateLimiterFn = (callback: (i: AxiosInstance | AxiosCacheInstance) => T) => Promise; +type ApiRateLimiterFn = (callback: (i: AxiosInstance | AxiosCacheInstance) => T) => Promise; export const apiRateLimiter = (name: string, options: ApiRateLimiterOptions): ApiRateLimiterFn => { const rateLimiter = new RateLimiterMemory({ diff --git a/server/src/common/utils/getStaticFilePath.ts b/server/src/common/utils/getStaticFilePath.ts index 015a925..2185786 100644 --- a/server/src/common/utils/getStaticFilePath.ts +++ b/server/src/common/utils/getStaticFilePath.ts @@ -2,7 +2,7 @@ import path from "path"; import { __dirname } from "./esmUtils"; -export function getStaticDirPath(): string { +function getStaticDirPath(): string { // tsup build project into a single file to dist/index.js // Hence import.meta.url references dist/index.js if (process.env.IS_BUILT === "true") { diff --git a/server/src/modules/actions/cerfa.actions.ts b/server/src/modules/actions/cerfa.actions.ts index 6b3aad7..8eb5181 100644 --- a/server/src/modules/actions/cerfa.actions.ts +++ b/server/src/modules/actions/cerfa.actions.ts @@ -11,7 +11,7 @@ import { PdfField, pdfFields } from "../server/utils/cerfaUtils"; const PATH_EMPTY_CERFA_PDF = getStaticFilePath("./cerfa/cerfa_10103-12_modif.pdf"); const PATH_CERFA_GUIDE_PDF = getStaticFilePath("./cerfa/guide_cerfa_apprentissage.pdf"); -export const getValueForPdf = (formValue: string | undefined, field: PdfField): string | boolean => { +const getValueForPdf = (formValue: string | undefined, field: PdfField): string | boolean => { if (!formValue) return ""; if (formValue === "") return ""; @@ -121,7 +121,7 @@ export const createCerfaPdf = async (rawData: Record) => { return pdfDoc.save(); }; -export const createCerfaErrorsPdf = async (errors: Record) => { +const createCerfaErrorsPdf = async (errors: Record) => { const pdfDoc = await PDFDocument.create(); await drawCerfaErrors(pdfDoc, errors); @@ -129,7 +129,7 @@ export const createCerfaErrorsPdf = async (errors: Record) => { return pdfDoc.save(); }; -export const createCerfaGuidePdf = async () => { +const createCerfaGuidePdf = async () => { return fs.readFile(PATH_CERFA_GUIDE_PDF); }; diff --git a/server/src/modules/server/middlewares/errorMiddleware.ts b/server/src/modules/server/middlewares/errorMiddleware.ts index 5a3da68..d7abe40 100644 --- a/server/src/modules/server/middlewares/errorMiddleware.ts +++ b/server/src/modules/server/middlewares/errorMiddleware.ts @@ -18,7 +18,7 @@ function getZodMessageError(error: ZodError, context: string): string { }, ""); } -export function boomify(rawError: FastifyError | Boom.Boom | Error | ZodError): Boom.Boom { +function boomify(rawError: FastifyError | Boom.Boom | Error | ZodError): Boom.Boom { if (Boom.isBoom(rawError)) { return rawError; } diff --git a/server/src/modules/server/server.ts b/server/src/modules/server/server.ts index 12f2e52..34deb4d 100644 --- a/server/src/modules/server/server.ts +++ b/server/src/modules/server/server.ts @@ -78,7 +78,7 @@ export default async (): Promise => { type RegisterRoutes = (opts: { server: Server }) => void; -export const registerRoutes: RegisterRoutes = ({ server }) => { +const registerRoutes: RegisterRoutes = ({ server }) => { coreRoutes({ server }); cerfaRoutes({ server }); controlsRoutes({ server }); diff --git a/server/src/modules/server/utils/geoUtils.ts b/server/src/modules/server/utils/geoUtils.ts index d46e544..312c03b 100644 --- a/server/src/modules/server/utils/geoUtils.ts +++ b/server/src/modules/server/utils/geoUtils.ts @@ -1,5 +1,4 @@ import { - findAddressFromGeoCoordinates, findCode, findDataByDepartementNum, findGeoCoordinateFromAdresse, @@ -92,44 +91,3 @@ export const getCoordinatesFromAddressData = async ({ }, }; }; -// @ts-expect-error: TODO -export const getAddressDataFromCoordinates = async ({ latitude, longitude }) => { - const result = await findAddressFromGeoCoordinates({ latitude, longitude }); - - if (result.count === 0) { - return { - result: {}, - messages: { - error: `Erreur: Aucun résultat pour les coordonnées ${latitude}, ${longitude}`, - }, - }; - } - - // @ts-expect-error: TODO - const { insee_com, code_dept, postal_code, nom_comm, nom_voie, numero_voie, type_voie } = result.value; - - const { nom_dept, nom_region, code_region, nom_academie, num_academie } = findDataByDepartementNum(code_dept); - - return { - result: { - adresse: { - numero_voie, - type_voie, - nom_voie, - code_postal: postal_code, - code_commune_insee: insee_com, - commune: nom_comm, - num_departement: code_dept, - nom_departement: nom_dept, - region: nom_region, - num_region: code_region, - nom_academie: nom_academie, - num_academie: `${num_academie}`, - }, - results_count: result.count, - }, - messages: { - adresse: result.info, - }, - }; -}; diff --git a/shared/constants/categoriesJuridiques.ts b/shared/constants/categoriesJuridiques.ts index 8c3b184..1133e09 100644 --- a/shared/constants/categoriesJuridiques.ts +++ b/shared/constants/categoriesJuridiques.ts @@ -5,7 +5,7 @@ export enum Siasp { HORS_FONCTION_PUBLIQUE = "HFP", } -export interface CategoryJuridique { +interface CategoryJuridique { category_juridique_id: string; libelle: string; siasp: "FPE" | "FPH" | "FPT" | "HFP"; diff --git a/shared/constants/diplomes.ts b/shared/constants/diplomes.ts index 6dd9d16..c7ec968 100644 --- a/shared/constants/diplomes.ts +++ b/shared/constants/diplomes.ts @@ -140,7 +140,7 @@ export const NIVEAUX_DIPLOMES = [ { value: "8", label: "8 - Doctorat, habilitation à diriger des recherches " }, ]; -export const codeDiplomeStartToDiplome: Record = { +const codeDiplomeStartToDiplome: Record = { "010": "35", "013": "35", "100": "80", diff --git a/shared/constants/idcc.ts b/shared/constants/idcc.ts index e319a9f..477060f 100644 --- a/shared/constants/idcc.ts +++ b/shared/constants/idcc.ts @@ -1,4 +1,4 @@ -export const IDCC_ETATS_JURIDIQUE = { +const IDCC_ETATS_JURIDIQUE = { VIGUEUR_ETEN: "VIGUEUR_ETEN", VIGUEUR_NON_ETEN: "VIGUEUR_NON_ETEN", MODIFIE: "MODIFIE", diff --git a/shared/constants/index.ts b/shared/constants/index.ts deleted file mode 100644 index 73cb05e..0000000 --- a/shared/constants/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -const megaByte = 1024 ** 2; -export const FILE_SIZE_LIMIT = 100 * megaByte; diff --git a/shared/constants/opcos.ts b/shared/constants/opcos.ts index 946b354..4b5ade8 100644 --- a/shared/constants/opcos.ts +++ b/shared/constants/opcos.ts @@ -5,7 +5,7 @@ export interface Opco { simulatorUrl?: string; } -export interface OpcoIdcc { +interface OpcoIdcc { idcc: string; opco: string; } diff --git a/shared/constants/pays.ts b/shared/constants/pays.ts deleted file mode 100644 index 6ea13be..0000000 --- a/shared/constants/pays.ts +++ /dev/null @@ -1,387 +0,0 @@ -export const PAYS = [ - { code: "AF", label: "AFGHANISTAN", value: "AFGHANISTAN", libelle: "ÉTAT ISLAMIQUE D'AFGHANISTAN", actif: "Oui" }, - { - code: "ZA", - label: "AFRIQUE DU SUD", - value: "AFRIQUE DU SUD", - libelle: "RÉPUBLIQUE D'AFRIQUE DU SUD", - actif: "Oui", - }, - { code: "AL", label: "ALBANIE", value: "ALBANIE", libelle: "RÉPUBLIQUE D'ALBANIE", actif: "Oui" }, - { - code: "DZ", - label: "ALGERIE", - value: "ALGERIE", - libelle: "RÉPUBLIQUE ALGÉRIENNE DÉMOCRATIQUE ET POPULAIRE", - actif: "Oui", - }, - { code: "DE", label: "ALLEMAGNE", value: "ALLEMAGNE", libelle: "RÉPUBLIQUE FÉDÉRALE D'ALLEMAGNE", actif: "Oui" }, - { code: "AD", label: "ANDORRE", value: "ANDORRE", libelle: "PRINCIPAUTÉ D'ANDORRE", actif: "Oui" }, - { code: "AO", label: "ANGOLA", value: "ANGOLA", libelle: "RÉPUBLIQUE D'ANGOLA", actif: "Oui" }, - { code: "AG", label: "ANTIGUA-ET-BARBUDA", value: "ANTIGUA-ET-BARBUDA", libelle: "ANTIGUA-ET-BARBUDA", actif: "Oui" }, - { - code: "SA", - label: "ARABIE SAOUDITE", - value: "ARABIE SAOUDITE", - libelle: "ROYAUME D'ARABIE SAOUDITE", - actif: "Oui", - }, - { code: "AR", label: "ARGENTINE", value: "ARGENTINE", libelle: "RÉPUBLIQUE ARGENTINE", actif: "Oui" }, - { code: "AM", label: "ARMENIE", value: "ARMENIE", libelle: "RÉPUBLIQUE D'ARMÉNIE", actif: "Oui" }, - { code: "AU", label: "AUSTRALIE", value: "AUSTRALIE", libelle: "AUSTRALIE", actif: "Oui" }, - { code: "AT", label: "AUTRICHE", value: "AUTRICHE", libelle: "RÉPUBLIQUE D'AUTRICHE", actif: "Oui" }, - { code: "AZ", label: "AZERBAIDJAN", value: "AZERBAIDJAN", libelle: "RÉPUBLIQUE AZERBAÏDJANAISE", actif: "Oui" }, - { code: "BS", label: "BAHAMAS", value: "BAHAMAS", libelle: "COMMONWEALTH DES BAHAMAS", actif: "Oui" }, - { code: "BH", label: "BAHREIN", value: "BAHREIN", libelle: "ÉTAT DE BAHREÏN", actif: "Oui" }, - { code: "BD", label: "BANGLADESH", value: "BANGLADESH", libelle: "RÉPUBLIQUE POPULAIRE DU BANGLADESH", actif: "Oui" }, - { code: "BB", label: "BARBADE", value: "BARBADE", libelle: "BARBADE", actif: "Oui" }, - { code: "BE", label: "BELGIQUE", value: "BELGIQUE", libelle: "ROYAUME DE BELGIQUE", actif: "Oui" }, - { code: "BZ", label: "BELIZE", value: "BELIZE", libelle: "BELIZE", actif: "Oui" }, - { code: "BJ", label: "BENIN", value: "BENIN", libelle: "RÉPUBLIQUE DU BÉNIN", actif: "Oui" }, - { code: "BT", label: "BHOUTAN", value: "BHOUTAN", libelle: "ROYAUME DU BHOUTAN", actif: "Oui" }, - { code: "BY", label: "BIELORUSSIE", value: "BIELORUSSIE", libelle: "RÉPUBLIQUE DE BIÉLORUSSIE", actif: "Oui" }, - { code: "MM", label: "BIRMANIE", value: "BIRMANIE", libelle: "UNION DE BIRMANIE", actif: "Oui" }, - { code: "BO", label: "BOLIVIE", value: "BOLIVIE", libelle: "ÉTAT PLURINATIONAL DE BOLIVIE", actif: "Oui" }, - { - code: "BQ", - label: "BONAIRE, SAINT EUSTACHE ET SABA", - value: "BONAIRE, SAINT EUSTACHE ET SABA", - libelle: "BONAIRE, SAINT EUSTACHE ET SABA", - actif: "Oui", - }, - { - code: "BA", - label: "BOSNIE-HERZEGOVINE", - value: "BOSNIE-HERZEGOVINE", - libelle: "RÉPUBLIQUE DE BOSNIE-HERZÉGOVINE", - actif: "Oui", - }, - { code: "BW", label: "BOTSWANA", value: "BOTSWANA", libelle: "RÉPUBLIQUE DU BOTSWANA", actif: "Oui" }, - { code: "BR", label: "BRESIL", value: "BRESIL", libelle: "RÉPUBLIQUE FÉDÉRATIVE DU BRÉSIL", actif: "Oui" }, - { code: "BN", label: "BRUNEI", value: "BRUNEI", libelle: "NEGARA BRUNEI DARUSSALAM", actif: "Oui" }, - { code: "BG", label: "BULGARIE", value: "BULGARIE", libelle: "RÉPUBLIQUE DE BULGARIE", actif: "Oui" }, - { code: "BF", label: "BURKINA", value: "BURKINA", libelle: "BURKINA FASO", actif: "Oui" }, - { code: "BI", label: "BURUNDI", value: "BURUNDI", libelle: "RÉPUBLIQUE DU BURUNDI", actif: "Oui" }, - { code: "KH", label: "CAMBODGE", value: "CAMBODGE", libelle: "ROYAUME DU CAMBODGE", actif: "Oui" }, - { code: "CM", label: "CAMEROUN", value: "CAMEROUN", libelle: "RÉPUBLIQUE DU CAMEROUN", actif: "Oui" }, - { code: "CA", label: "CANADA", value: "CANADA", libelle: "CANADA", actif: "Oui" }, - { code: "CV", label: "CAP-VERT", value: "CAP-VERT", libelle: "RÉPUBLIQUE DU CAP-VERT", actif: "Oui" }, - { - code: "CF", - label: "CENTRAFRICAINE (REPUBLIQUE)", - value: "CENTRAFRICAINE (REPUBLIQUE)", - libelle: "RÉPUBLIQUE CENTRAFRICAINE", - actif: "Oui", - }, - { code: "CL", label: "CHILI", value: "CHILI", libelle: "RÉPUBLIQUE DU CHILI", actif: "Oui" }, - { code: "CN", label: "CHINE", value: "CHINE", libelle: "RÉPUBLIQUE POPULAIRE DE CHINE", actif: "Oui" }, - { code: "CY", label: "CHYPRE", value: "CHYPRE", libelle: "RÉPUBLIQUE DE CHYPRE", actif: "Oui" }, - { code: "CO", label: "COLOMBIE", value: "COLOMBIE", libelle: "RÉPUBLIQUE DE COLOMBIE", actif: "Oui" }, - { - code: "KM", - label: "COMORES", - value: "COMORES", - libelle: "RÉPUBLIQUE FÉDÉRALE ISLAMIQUE DES COMORES", - actif: "Oui", - }, - { code: "CG", label: "CONGO", value: "CONGO", libelle: "RÉPUBLIQUE DU CONGO", actif: "Oui" }, - { - code: "CD", - label: "CONGO (REPUBLIQUE DEMOCRATIQUE)", - value: "CONGO (REPUBLIQUE DEMOCRATIQUE)", - libelle: "RÉPUBLIQUE DÉMOCRATIQUE DU CONGO", - actif: "Oui", - }, - { - code: "KR", - label: "COREE (REPUBLIQUE DE)", - value: "COREE (REPUBLIQUE DE)", - libelle: "RÉPUBLIQUE DE CORÉE", - actif: "Oui", - }, - { - code: "KP", - label: "COREE (REPUBLIQUE POPULAIRE DEMOCRATIQUE DE)", - value: "COREE (REPUBLIQUE POPULAIRE DEMOCRATIQUE DE)", - libelle: "RÉPUBLIQUE POPULAIRE DÉMOCRATIQUE DE CORÉE", - actif: "Oui", - }, - { code: "CR", label: "COSTA RICA", value: "COSTA RICA", libelle: "RÉPUBLIQUE DU COSTA RICA", actif: "Oui" }, - { code: "CI", label: "COTE D'IVOIRE", value: "COTE D'IVOIRE", libelle: "RÉPUBLIQUE DE CÔTE D'IVOIRE", actif: "Oui" }, - { code: "HR", label: "CROATIE", value: "CROATIE", libelle: "RÉPUBLIQUE DE CROATIE", actif: "Oui" }, - { code: "CU", label: "CUBA", value: "CUBA", libelle: "RÉPUBLIQUE DE CUBA", actif: "Oui" }, - { code: "CW", label: "CURAÇAO", value: "CURAÇAO", libelle: "CURAÇAO", actif: "Oui" }, - { code: "DK", label: "DANEMARK", value: "DANEMARK", libelle: "ROYAUME DU DANEMARK", actif: "Oui" }, - { code: "DJ", label: "DJIBOUTI", value: "DJIBOUTI", libelle: "RÉPUBLIQUE DE DJIBOUTI", actif: "Oui" }, - { - code: "DO", - label: "DOMINICAINE (REPUBLIQUE)", - value: "DOMINICAINE (REPUBLIQUE)", - libelle: "RÉPUBLIQUE DOMINICAINE", - actif: "Oui", - }, - { code: "DM", label: "DOMINIQUE", value: "DOMINIQUE", libelle: "COMMONWEALTH DE DOMINIQUE", actif: "Oui" }, - { code: "EG", label: "EGYPTE", value: "EGYPTE", libelle: "RÉPUBLIQUE ARABE D'ÉGYPTE", actif: "Oui" }, - { code: "SV", label: "EL SALVADOR", value: "EL SALVADOR", libelle: "RÉPUBLIQUE DU SALVADOR", actif: "Oui" }, - { - code: "AE", - label: "EMIRATS ARABES UNIS", - value: "EMIRATS ARABES UNIS", - libelle: "ÉMIRATS ARABES UNIS", - actif: "Oui", - }, - { code: "EC", label: "EQUATEUR", value: "EQUATEUR", libelle: "RÉPUBLIQUE DE L'ÉQUATEUR", actif: "Oui" }, - { code: "ER", label: "ERYTHREE", value: "ERYTHREE", libelle: "ÉTAT D'ÉRYTHRÉE", actif: "Oui" }, - { code: "ES", label: "ESPAGNE", value: "ESPAGNE", libelle: "ROYAUME D'ESPAGNE", actif: "Oui" }, - { code: "EE", label: "ESTONIE", value: "ESTONIE", libelle: "RÉPUBLIQUE D'ESTONIE", actif: "Oui" }, - { code: "SZ", label: "ESWATINI", value: "ESWATINI", libelle: "ROYAUME D'ESWATINI", actif: "Oui" }, - { code: "US", label: "ETATS-UNIS", value: "ETATS-UNIS", libelle: "ÉTATS-UNIS D'AMÉRIQUE", actif: "Oui" }, - { - code: "ET", - label: "ETHIOPIE", - value: "ETHIOPIE", - libelle: "RÉPUBLIQUE DÉMOCRATIQUE FÉDÉRALE D'ÉTHIOPIE", - actif: "Oui", - }, - { - code: "MK", - label: "EX-REPUBLIQUE YOUGOSLAVE DE MACEDOINE", - value: "EX-REPUBLIQUE YOUGOSLAVE DE MACEDOINE", - libelle: "EX-RÉPUBLIQUE YOUGOSLAVE DE MACÉDOINE", - actif: "Oui", - }, - { code: "FJ", label: "FIDJI", value: "FIDJI", libelle: "RÉPUBLIQUE DES FIDJI", actif: "Oui" }, - { code: "FI", label: "FINLANDE", value: "FINLANDE", libelle: "RÉPUBLIQUE DE FINLANDE", actif: "Oui" }, - { code: "FR", label: "FRANCE", value: "FRANCE", libelle: "RÉPUBLIQUE FRANÇAISE", actif: "Oui" }, - { code: "GA", label: "GABON", value: "GABON", libelle: "RÉPUBLIQUE GABONAISE", actif: "Oui" }, - { code: "GM", label: "GAMBIE", value: "GAMBIE", libelle: "RÉPUBLIQUE DE GAMBIE", actif: "Oui" }, - { code: "GE", label: "GEORGIE", value: "GEORGIE", libelle: "RÉPUBLIQUE DE GÉORGIE", actif: "Oui" }, - { code: "GH", label: "GHANA", value: "GHANA", libelle: "RÉPUBLIQUE DU GHANA", actif: "Oui" }, - { code: "GR", label: "GRECE", value: "GRECE", libelle: "RÉPUBLIQUE HELLÉNIQUE", actif: "Oui" }, - { code: "GD", label: "GRENADE", value: "GRENADE", libelle: "GRENADE", actif: "Oui" }, - { code: "GT", label: "GUATEMALA", value: "GUATEMALA", libelle: "RÉPUBLIQUE DU GUATEMALA", actif: "Oui" }, - { code: "GN", label: "GUINEE", value: "GUINEE", libelle: "RÉPUBLIQUE DE GUINÉE", actif: "Oui" }, - { - code: "GQ", - label: "GUINEE EQUATORIALE", - value: "GUINEE EQUATORIALE", - libelle: "RÉPUBLIQUE DE GUINÉE ÉQUATORIALE", - actif: "Oui", - }, - { code: "GW", label: "GUINEE-BISSAU", value: "GUINEE-BISSAU", libelle: "RÉPUBLIQUE DE GUINÉE-BISSAU", actif: "Oui" }, - { code: "GY", label: "GUYANA", value: "GUYANA", libelle: "RÉPUBLIQUE COOPÉRATIVE DE GUYANA", actif: "Oui" }, - { code: "HT", label: "HAITI", value: "HAITI", libelle: "RÉPUBLIQUE D'HAÏTI", actif: "Oui" }, - { code: "HN", label: "HONDURAS", value: "HONDURAS", libelle: "RÉPUBLIQUE DU HONDURAS", actif: "Oui" }, - { code: "HU", label: "HONGRIE", value: "HONGRIE", libelle: "RÉPUBLIQUE DE HONGRIE", actif: "Oui" }, - { code: "IN", label: "INDE", value: "INDE", libelle: "RÉPUBLIQUE DE L'INDE", actif: "Oui" }, - { code: "ID", label: "INDONESIE", value: "INDONESIE", libelle: "RÉPUBLIQUE D'INDONÉSIE", actif: "Oui" }, - { code: "IR", label: "IRAN", value: "IRAN", libelle: "RÉPUBLIQUE ISLAMIQUE D'IRAN", actif: "Oui" }, - { code: "IQ", label: "IRAQ", value: "IRAQ", libelle: "RÉPUBLIQUE D'IRAQ", actif: "Oui" }, - { code: "IE", label: "IRLANDE, ou EIRE", value: "IRLANDE, ou EIRE", libelle: "IRLANDE", actif: "Oui" }, - { code: "IS", label: "ISLANDE", value: "ISLANDE", libelle: "RÉPUBLIQUE D'ISLANDE", actif: "Oui" }, - { code: "IL", label: "ISRAEL", value: "ISRAEL", libelle: "ÉTAT D'ISRAËL", actif: "Oui" }, - { code: "IT", label: "ITALIE", value: "ITALIE", libelle: "RÉPUBLIQUE ITALIENNE", actif: "Oui" }, - { code: "JM", label: "JAMAIQUE", value: "JAMAIQUE", libelle: "JAMAÏQUE", actif: "Oui" }, - { code: "JP", label: "JAPON", value: "JAPON", libelle: "JAPON", actif: "Oui" }, - { code: "JO", label: "JORDANIE", value: "JORDANIE", libelle: "ROYAUME HACHÉMITE DE JORDANIE", actif: "Oui" }, - { code: "KZ", label: "KAZAKHSTAN", value: "KAZAKHSTAN", libelle: "RÉPUBLIQUE DU KAZAKHSTAN", actif: "Oui" }, - { code: "KE", label: "KENYA", value: "KENYA", libelle: "RÉPUBLIQUE DU KENYA", actif: "Oui" }, - { code: "KG", label: "KIRGHIZISTAN", value: "KIRGHIZISTAN", libelle: "RÉPUBLIQUE KIRGHIZE", actif: "Oui" }, - { code: "KI", label: "KIRIBATI", value: "KIRIBATI", libelle: "RÉPUBLIQUE DE KIRIBATI", actif: "Oui" }, - { code: "XK", label: "KOSOVO", value: "KOSOVO", libelle: "RÉPUBLIQUE DU KOSOVO", actif: "Oui" }, - { code: "KW", label: "KOWEIT", value: "KOWEIT", libelle: "ÉTAT DU KOWEÏT", actif: "Oui" }, - { code: "LA", label: "LAOS", value: "LAOS", libelle: "RÉPUBLIQUE DÉMOCRATIQUE POPULAIRE LAO", actif: "Oui" }, - { code: "LS", label: "LESOTHO", value: "LESOTHO", libelle: "ROYAUME DU LESOTHO", actif: "Oui" }, - { code: "LV", label: "LETTONIE", value: "LETTONIE", libelle: "RÉPUBLIQUE DE LETTONIE", actif: "Oui" }, - { code: "LB", label: "LIBAN", value: "LIBAN", libelle: "RÉPUBLIQUE LIBANAISE", actif: "Oui" }, - { code: "LR", label: "LIBERIA", value: "LIBERIA", libelle: "RÉPUBLIQUE DU LIBERIA", actif: "Oui" }, - { - code: "LY", - label: "LIBYE", - value: "LIBYE", - libelle: "JAMAHIRIYA ARABE LIBYENNE POPULAIRE ET SOCIALISTE", - actif: "Oui", - }, - { code: "LI", label: "LIECHTENSTEIN", value: "LIECHTENSTEIN", libelle: "PRINCIPAUTÉ DE LIECHTENSTEIN", actif: "Oui" }, - { code: "LT", label: "LITUANIE", value: "LITUANIE", libelle: "RÉPUBLIQUE DE LITUANIE", actif: "Oui" }, - { code: "LU", label: "LUXEMBOURG", value: "LUXEMBOURG", libelle: "GRAND-DUCHÉ DE LUXEMBOURG", actif: "Oui" }, - { code: "MG", label: "MADAGASCAR", value: "MADAGASCAR", libelle: "RÉPUBLIQUE DE MADAGASCAR", actif: "Oui" }, - { code: "MY", label: "MALAISIE", value: "MALAISIE", libelle: "MALAISIE", actif: "Oui" }, - { code: "MW", label: "MALAWI", value: "MALAWI", libelle: "RÉPUBLIQUE DU MALAWI", actif: "Oui" }, - { code: "MV", label: "MALDIVES", value: "MALDIVES", libelle: "RÉPUBLIQUE DES MALDIVES", actif: "Oui" }, - { code: "ML", label: "MALI", value: "MALI", libelle: "RÉPUBLIQUE DU MALI", actif: "Oui" }, - { code: "MT", label: "MALTE", value: "MALTE", libelle: "RÉPUBLIQUE DE MALTE", actif: "Oui" }, - { code: "MA", label: "MAROC", value: "MAROC", libelle: "ROYAUME DU MAROC", actif: "Oui" }, - { - code: "MH", - label: "MARSHALL (ILES)", - value: "MARSHALL (ILES)", - libelle: "RÉPUBLIQUE DES ÎLES MARSHALL", - actif: "Oui", - }, - { code: "MU", label: "MAURICE", value: "MAURICE", libelle: "RÉPUBLIQUE DE MAURICE", actif: "Oui" }, - { code: "MR", label: "MAURITANIE", value: "MAURITANIE", libelle: "RÉPUBLIQUE ISLAMIQUE DE MAURITANIE", actif: "Oui" }, - { code: "MX", label: "MEXIQUE", value: "MEXIQUE", libelle: "ÉTATS-UNIS DU MEXIQUE", actif: "Oui" }, - { - code: "FM", - label: "MICRONESIE (ETATS FEDERES DE)", - value: "MICRONESIE (ETATS FEDERES DE)", - libelle: "ÉTATS FÉDÉRÉS DE MICRONÉSIE", - actif: "Oui", - }, - { code: "MD", label: "MOLDAVIE", value: "MOLDAVIE", libelle: "RÉPUBLIQUE DE MOLDAVIE", actif: "Oui" }, - { code: "MC", label: "MONACO", value: "MONACO", libelle: "PRINCIPAUTÉ DE MONACO", actif: "Oui" }, - { code: "MN", label: "MONGOLIE", value: "MONGOLIE", libelle: "MONGOLIE", actif: "Oui" }, - { code: "ME", label: "MONTENEGRO", value: "MONTENEGRO", libelle: "RÉPUBLIQUE DU MONTÉNÉGRO", actif: "Oui" }, - { code: "MZ", label: "MOZAMBIQUE", value: "MOZAMBIQUE", libelle: "RÉPUBLIQUE DU MOZAMBIQUE", actif: "Oui" }, - { code: "NA", label: "NAMIBIE", value: "NAMIBIE", libelle: "RÉPUBLIQUE DE NAMIBIE", actif: "Oui" }, - { code: "NR", label: "NAURU", value: "NAURU", libelle: "RÉPUBLIQUE DE NAURU", actif: "Oui" }, - { code: "NP", label: "NEPAL", value: "NEPAL", libelle: "ROYAUME DU NÉPAL", actif: "Oui" }, - { code: "NI", label: "NICARAGUA", value: "NICARAGUA", libelle: "RÉPUBLIQUE DU NICARAGUA", actif: "Oui" }, - { code: "NE", label: "NIGER", value: "NIGER", libelle: "RÉPUBLIQUE DU NIGER", actif: "Oui" }, - { code: "NG", label: "NIGERIA", value: "NIGERIA", libelle: "RÉPUBLIQUE FÉDÉRALE DU NIGÉRIA", actif: "Oui" }, - { code: "NO", label: "NORVEGE", value: "NORVEGE", libelle: "ROYAUME DE NORVÈGE", actif: "Oui" }, - { code: "NZ", label: "NOUVELLE-ZELANDE", value: "NOUVELLE-ZELANDE", libelle: "NOUVELLE-ZÉLANDE", actif: "Oui" }, - { code: "OM", label: "OMAN", value: "OMAN", libelle: "SULTANAT D'OMAN", actif: "Oui" }, - { code: "UG", label: "OUGANDA", value: "OUGANDA", libelle: "RÉPUBLIQUE DE L'OUGANDA", actif: "Oui" }, - { code: "UZ", label: "OUZBEKISTAN", value: "OUZBEKISTAN", libelle: "RÉPUBLIQUE D'OUZBÉKISTAN", actif: "Oui" }, - { code: "PK", label: "PAKISTAN", value: "PAKISTAN", libelle: "RÉPUBLIQUE ISLAMIQUE DU PAKISTAN", actif: "Oui" }, - { code: "PW", label: "PALAOS (ILES)", value: "PALAOS (ILES)", libelle: "RÉPUBLIQUE DES ÎLES PALAOS", actif: "Oui" }, - { - code: "PS", - label: "PALESTINE (État de)", - value: "PALESTINE (État de)", - libelle: "ÉTAT DE PALESTINE", - actif: "Oui", - }, - { code: "PA", label: "PANAMA", value: "PANAMA", libelle: "RÉPUBLIQUE DU PANAMA", actif: "Oui" }, - { - code: "PG", - label: "PAPOUASIE-NOUVELLE-GUINEE", - value: "PAPOUASIE-NOUVELLE-GUINEE", - libelle: "PAPOUASIE-NOUVELLE-GUINÉE", - actif: "Oui", - }, - { code: "PY", label: "PARAGUAY", value: "PARAGUAY", libelle: "RÉPUBLIQUE DU PARAGUAY", actif: "Oui" }, - { code: "NL", label: "PAYS-BAS", value: "PAYS-BAS", libelle: "ROYAUME DES PAYS-BAS", actif: "Oui" }, - { code: "PE", label: "PEROU", value: "PEROU", libelle: "RÉPUBLIQUE DU PÉROU", actif: "Oui" }, - { code: "PH", label: "PHILIPPINES", value: "PHILIPPINES", libelle: "RÉPUBLIQUE DES PHILIPPINES", actif: "Oui" }, - { code: "PL", label: "POLOGNE", value: "POLOGNE", libelle: "RÉPUBLIQUE DE POLOGNE", actif: "Oui" }, - { code: "PT", label: "PORTUGAL", value: "PORTUGAL", libelle: "RÉPUBLIQUE PORTUGAISE", actif: "Oui" }, - { code: "QA", label: "QATAR", value: "QATAR", libelle: "ÉTAT DU QATAR", actif: "Oui" }, - { code: "RO", label: "ROUMANIE", value: "ROUMANIE", libelle: "ROUMANIE", actif: "Oui" }, - { - code: "GB", - label: "ROYAUME-UNI", - value: "ROYAUME-UNI", - libelle: "ROYAUME-UNI DE GRANDE-BRETAGNE ET D'IRLANDE DU NORD", - actif: "Oui", - }, - { code: "RU", label: "RUSSIE", value: "RUSSIE", libelle: "FÉDÉRATION DE RUSSIE", actif: "Oui" }, - { code: "RW", label: "RWANDA", value: "RWANDA", libelle: "RÉPUBLIQUE RWANDAISE", actif: "Oui" }, - { - code: "KN", - label: "SAINT-CHRISTOPHE-ET-NIEVES", - value: "SAINT-CHRISTOPHE-ET-NIEVES", - libelle: "FÉDÉRATION DE SAINT-CHRISTOPHE-ET-NIÉVÈS", - actif: "Oui", - }, - { code: "SM", label: "SAINT-MARIN", value: "SAINT-MARIN", libelle: "RÉPUBLIQUE DE SAINT-MARIN", actif: "Oui" }, - { - code: "SX", - label: "SAINT-MARTIN (PARTIE NEERLANDAISE)", - value: "SAINT-MARTIN (PARTIE NEERLANDAISE)", - libelle: "SAINT-MARTIN (PARTIE NÉERLANDAISE)", - actif: "Oui", - }, - { - code: "VC", - label: "SAINT-VINCENT-ET-LES GRENADINES", - value: "SAINT-VINCENT-ET-LES GRENADINES", - libelle: "SAINT-VINCENT-ET-LES GRENADINES", - actif: "Oui", - }, - { code: "LC", label: "SAINTE-LUCIE", value: "SAINTE-LUCIE", libelle: "SAINTE-LUCIE", actif: "Oui" }, - { code: "SB", label: "SALOMON (ILES)", value: "SALOMON (ILES)", libelle: "ÎLES SALOMON", actif: "Oui" }, - { - code: "WS", - label: "SAMOA OCCIDENTALES", - value: "SAMOA OCCIDENTALES", - libelle: "ÉTAT INDÉPENDANT DES SAMOA OCCIDENTALES", - actif: "Oui", - }, - { - code: "ST", - label: "SAO TOME-ET-PRINCIPE", - value: "SAO TOME-ET-PRINCIPE", - libelle: "RÉPUBLIQUE DÉMOCRATIQUE DE SAO TOMÉ-ET-PRINCIPE", - actif: "Oui", - }, - { code: "SN", label: "SENEGAL", value: "SENEGAL", libelle: "RÉPUBLIQUE DU SÉNÉGAL", actif: "Oui" }, - { code: "RS", label: "SERBIE", value: "SERBIE", libelle: "RÉPUBLIQUE DE SERBIE", actif: "Oui" }, - { code: "SC", label: "SEYCHELLES", value: "SEYCHELLES", libelle: "RÉPUBLIQUE DES SEYCHELLES", actif: "Oui" }, - { code: "SL", label: "SIERRA LEONE", value: "SIERRA LEONE", libelle: "RÉPUBLIQUE DE SIERRA LEONE", actif: "Oui" }, - { code: "SG", label: "SINGAPOUR", value: "SINGAPOUR", libelle: "RÉPUBLIQUE DE SINGAPOUR", actif: "Oui" }, - { code: "SK", label: "SLOVAQUIE", value: "SLOVAQUIE", libelle: "RÉPUBLIQUE SLOVAQUE", actif: "Oui" }, - { code: "SI", label: "SLOVENIE", value: "SLOVENIE", libelle: "RÉPUBLIQUE DE SLOVÉNIE", actif: "Oui" }, - { code: "SO", label: "SOMALIE", value: "SOMALIE", libelle: "SOMALIE", actif: "Oui" }, - { code: "SD", label: "SOUDAN", value: "SOUDAN", libelle: "RÉPUBLIQUE DU SOUDAN", actif: "Oui" }, - { code: "SS", label: "SOUDAN DU SUD", value: "SOUDAN DU SUD", libelle: "RÉPUBLIQUE DU SOUDAN DU SUD", actif: "Oui" }, - { - code: "LK", - label: "SRI LANKA", - value: "SRI LANKA", - libelle: "RÉPUBLIQUE DÉMOCRATIQUE SOCIALISTE DU SRI LANKA", - actif: "Oui", - }, - { code: "SE", label: "SUEDE", value: "SUEDE", libelle: "ROYAUME DE SUÈDE", actif: "Oui" }, - { code: "CH", label: "SUISSE", value: "SUISSE", libelle: "CONFÉDÉRATION SUISSE", actif: "Oui" }, - { code: "SR", label: "SURINAME", value: "SURINAME", libelle: "RÉPUBLIQUE DU SURINAME", actif: "Oui" }, - { code: "SY", label: "SYRIE", value: "SYRIE", libelle: "RÉPUBLIQUE ARABE SYRIENNE", actif: "Oui" }, - { code: "TJ", label: "TADJIKISTAN", value: "TADJIKISTAN", libelle: "RÉPUBLIQUE DU TADJIKISTAN", actif: "Oui" }, - { code: "TZ", label: "TANZANIE", value: "TANZANIE", libelle: "RÉPUBLIQUE UNIE DE TANZANIE", actif: "Oui" }, - { code: "TD", label: "TCHAD", value: "TCHAD", libelle: "RÉPUBLIQUE DU TCHAD", actif: "Oui" }, - { - code: "CZ", - label: "TCHEQUE (REPUBLIQUE)", - value: "TCHEQUE (REPUBLIQUE)", - libelle: "RÉPUBLIQUE TCHÈQUE", - actif: "Oui", - }, - { code: "TH", label: "THAILANDE", value: "THAILANDE", libelle: "ROYAUME DE THAÏLANDE", actif: "Oui" }, - { - code: "TL", - label: "TIMOR ORIENTAL", - value: "TIMOR ORIENTAL", - libelle: "RÉPUBLIQUE DÉMOCRATIQUE DU TIMOR ORIENTAL", - actif: "Oui", - }, - { code: "TG", label: "TOGO", value: "TOGO", libelle: "RÉPUBLIQUE TOGOLAISE", actif: "Oui" }, - { code: "TO", label: "TONGA", value: "TONGA", libelle: "ROYAUME DES TONGA", actif: "Oui" }, - { - code: "TT", - label: "TRINITE-ET-TOBAGO", - value: "TRINITE-ET-TOBAGO", - libelle: "RÉPUBLIQUE DE TRINITÉ-ET-TOBAGO", - actif: "Oui", - }, - { code: "TN", label: "TUNISIE", value: "TUNISIE", libelle: "RÉPUBLIQUE TUNISIENNE", actif: "Oui" }, - { code: "TM", label: "TURKMENISTAN", value: "TURKMENISTAN", libelle: "TURKMÉNISTAN", actif: "Oui" }, - { code: "TR", label: "TURQUIE", value: "TURQUIE", libelle: "RÉPUBLIQUE TURQUE", actif: "Oui" }, - { code: "TV", label: "TUVALU", value: "TUVALU", libelle: "TUVALU", actif: "Oui" }, - { code: "UA", label: "UKRAINE", value: "UKRAINE", libelle: "UKRAINE", actif: "Oui" }, - { code: "UY", label: "URUGUAY", value: "URUGUAY", libelle: "RÉPUBLIQUE ORIENTALE DE L'URUGUAY", actif: "Oui" }, - { code: "VU", label: "VANUATU", value: "VANUATU", libelle: "RÉPUBLIQUE DE VANUATU", actif: "Oui" }, - { - code: "VA", - label: "VATICAN, ou SAINT-SIEGE", - value: "VATICAN, ou SAINT-SIEGE", - libelle: "ÉTAT DE LA CITÉ DU VATICAN", - actif: "Oui", - }, - { code: "VE", label: "VENEZUELA", value: "VENEZUELA", libelle: "RÉPUBLIQUE BOLIVARIENNE DU VENEZUELA", actif: "Oui" }, - { code: "VN", label: "VIET NAM", value: "VIET NAM", libelle: "RÉPUBLIQUE SOCIALISTE DU VIÊT NAM", actif: "Oui" }, - { code: "YE", label: "YEMEN", value: "YEMEN", libelle: "RÉPUBLIQUE DU YÉMEN", actif: "Oui" }, - { code: "ZM", label: "ZAMBIE", value: "ZAMBIE", libelle: "RÉPUBLIQUE DE ZAMBIE", actif: "Oui" }, - { code: "ZW", label: "ZIMBABWE", value: "ZIMBABWE", libelle: "RÉPUBLIQUE DU ZIMBABWE", actif: "Oui" }, -]; diff --git a/shared/constants/regex.ts b/shared/constants/regex.ts deleted file mode 100644 index 843f53d..0000000 --- a/shared/constants/regex.ts +++ /dev/null @@ -1,36 +0,0 @@ -export const REPETITION_VOIE_MAPPING = { - Bis: "B", - Ter: "T", - Quater: "Q", - ["Quinquiès"]: "C", -}; - -export const CFD_REGEX_PATTERN = "^[A-Z0-9]{8}$"; -export const CODE_INSEE_PATTERN = "^[0-9]{1}[0-9A-Z]{1}[0-9]{3}$"; -export const CODE_POSTAL_PATTERN = "^[0-9]{5}$"; -export const RNCP_REGEX_PATTERN = "^(RNCP)?[0-9]{2,5}$"; -export const SIRET_REGEX_PATTERN = "^[0-9]{14}$"; -export const CODE_NAF_REGEX_PATTERN = "^[0-9]{4}[A-Z]$"; -export const UAI_REGEX_PATTERN = "^[0-9]{7}[a-zA-Z]$"; - -// Numero INE (Identifiant National Elève) -// Le numero INE composé de 11 caractères, -// soit 10 chiffres et 1 lettre soit 9 chiffres et 2 lettres (depuis la rentrée 2018). -// INE BEA (Base élèves académique) 123456789FF -const INE_RNIE_REGEX_PATTERN = "^[0-9]{9}[a-zA-Z]{2}$"; -// INE BEA (Base élèves académique) ex: 1234567890F -const INE_BEA_REGEX_PATTERN = "^[0-9_]{10}[a-zA-Z]{1}$"; -// INE APPRENTISSAGE 1234A12345F -const INE_APPRENTISSAGE_REGEX_PATTERN = "^[0-9]{4}A[0-9]{5}[a-zA-Z]{1}$"; -export const INE_REGEX_PATTERN = `^(${INE_RNIE_REGEX_PATTERN}|${INE_BEA_REGEX_PATTERN}|${INE_APPRENTISSAGE_REGEX_PATTERN})$`; - -export const CFD_REGEX = new RegExp(CFD_REGEX_PATTERN); -export const CODE_POSTAL_REGEX = new RegExp(CODE_POSTAL_PATTERN); -export const INE_REGEX = new RegExp(INE_REGEX_PATTERN); -export const RNCP_REGEX = new RegExp(RNCP_REGEX_PATTERN); -export const SIRET_REGEX = new RegExp(SIRET_REGEX_PATTERN); -export const CODE_NAF_REGEX = new RegExp(CODE_NAF_REGEX_PATTERN); -export const UAI_REGEX = new RegExp(UAI_REGEX_PATTERN); - -export const isValidCFD = (cfd: string) => typeof cfd === "string" && CFD_REGEX.test(cfd); -export const isValidINE = (ine: string) => typeof ine === "string" && INE_REGEX.test(ine); diff --git a/shared/constants/territoires.ts b/shared/constants/territoires.ts deleted file mode 100644 index 7d5016b..0000000 --- a/shared/constants/territoires.ts +++ /dev/null @@ -1,1586 +0,0 @@ -// données à synchroniser avec /ui/common/constants/territoiresConstants.js -// en attendant un import partagé - -/** - * Liste des régions du territoire national - * TODO : Rationaliser la liste des régions (point transverse tech ?) - * https://fr.wikipedia.org/wiki/Code_officiel_g%C3%A9ographique - */ -export const REGIONS = [ - { - nom: "Guadeloupe", - code: "01", - }, - { - nom: "Martinique", - code: "02", - }, - { - nom: "Guyane", - code: "03", - }, - { - nom: "La Réunion", - code: "04", - }, - { - nom: "Mayotte", - code: "06", - }, - { - nom: "Île-de-France", - code: "11", - shortName: "idf", - }, - { - nom: "Centre-Val de Loire", - code: "24", - shortName: "cvl", - }, - { - nom: "Bourgogne-Franche-Comté", - code: "27", - shortName: "bfc", - }, - { - nom: "Normandie", - code: "28", - }, - { - nom: "Hauts-de-France", - code: "32", - shortName: "hdf", - }, - { - nom: "Grand Est", - code: "44", - }, - { - nom: "Pays de la Loire", - code: "52", - shortName: "pdl", - }, - { - nom: "Bretagne", - code: "53", - }, - { - nom: "Nouvelle-Aquitaine", - code: "75", - shortName: "na", - }, - { - nom: "Occitanie", - code: "76", - }, - { - nom: "Auvergne-Rhône-Alpes", - code: "84", - shortName: "ara", - }, - { - nom: "Provence-Alpes-Côte d'Azur", - code: "93", - shortName: "paca", - }, - { - nom: "Corse", - code: "94", - }, - { - nom: "Saint-Martin", - code: "978", - }, - { - nom: "Saint-Barthélemy", - code: "977", - }, - { - nom: "Collectivité d'outre-mer", - code: "00", - }, -] as const; - -type Codes = (typeof REGIONS)[number]["code"]; - -type IRegion = { - code: C; - nom: string; -}; - -type IRegionPerId = { - [C in Codes]: IRegion; -}; - -export const REGIONS_BY_ID: IRegionPerId = REGIONS.reduce((acc, region) => { - acc[region.code] = region; - return acc; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -}, {} as any); - -export const DEPARTEMENTS = [ - { - nom: "Ain", - code: "01", - uaiCode: "01", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "10", - nom: "Lyon", - }, - }, - { - nom: "Aisne", - code: "02", - uaiCode: "02", - region: { - code: "32", - nom: "Hauts-de-France", - }, - academie: { - code: "20", - nom: "Amiens", - }, - }, - { - nom: "Allier", - code: "03", - uaiCode: "03", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "6", - nom: "Clermont-Ferrand", - }, - }, - { - nom: "Alpes-de-Haute-Provence", - code: "04", - uaiCode: "04", - region: { - code: "93", - nom: "Provence-Alpes-Côte d'Azur", - }, - academie: { - code: "2", - nom: "Aix-Marseille", - }, - }, - { - nom: "Hautes-Alpes", - code: "05", - uaiCode: "05", - region: { - code: "93", - nom: "Provence-Alpes-Côte d'Azur", - }, - academie: { - code: "2", - nom: "Aix-Marseille", - }, - }, - { - nom: "Alpes-Maritimes", - code: "06", - uaiCode: "06", - region: { - code: "93", - nom: "Provence-Alpes-Côte d'Azur", - }, - academie: { - code: "23", - nom: "Nice", - }, - }, - { - nom: "Ardèche", - code: "07", - uaiCode: "07", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "8", - nom: "Grenoble", - }, - }, - { - nom: "Ardennes", - code: "08", - uaiCode: "08", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "19", - nom: "Reims", - }, - }, - { - nom: "Ariège", - code: "09", - uaiCode: "09", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Aube", - code: "10", - uaiCode: "10", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "19", - nom: "Reims", - }, - }, - { - nom: "Aude", - code: "11", - uaiCode: "11", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "11", - nom: "Montpellier", - }, - }, - { - nom: "Aveyron", - code: "12", - uaiCode: "12", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Bouches-du-Rhône", - code: "13", - uaiCode: "13", - region: { - code: "93", - nom: "Provence-Alpes-Côte d'Azur", - }, - academie: { - code: "2", - nom: "Aix-Marseille", - }, - }, - { - nom: "Calvados", - code: "14", - uaiCode: "14", - region: { - code: "28", - nom: "Normandie", - }, - academie: { - code: "70", - nom: "Normandie", - }, - }, - { - nom: "Cantal", - code: "15", - uaiCode: "15", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "6", - nom: "Clermont-Ferrand", - }, - }, - { - nom: "Charente", - code: "16", - uaiCode: "16", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "13", - nom: "Poitiers", - }, - }, - { - nom: "Charente-Maritime", - code: "17", - uaiCode: "17", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "13", - nom: "Poitiers", - }, - }, - { - nom: "Cher", - code: "18", - uaiCode: "18", - region: { - code: "24", - nom: "Centre-Val de Loire", - }, - academie: { - code: "18", - nom: "Orléans-Tours", - }, - }, - { - nom: "Corrèze", - code: "19", - uaiCode: "19", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "22", - nom: "Limoges", - }, - }, - { - nom: "Côte-d'Or", - code: "21", - uaiCode: "21", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "7", - nom: "Dijon", - }, - }, - { - nom: "Côtes-d'Armor", - code: "22", - uaiCode: "22", - region: { - code: "53", - nom: "Bretagne", - }, - academie: { - code: "14", - nom: "Rennes", - }, - }, - { - nom: "Creuse", - code: "23", - uaiCode: "23", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "22", - nom: "Limoges", - }, - }, - { - nom: "Dordogne", - code: "24", - uaiCode: "24", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "4", - nom: "Bordeaux", - }, - }, - { - nom: "Doubs", - code: "25", - uaiCode: "25", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "3", - nom: "Besançon", - }, - }, - { - nom: "Drôme", - code: "26", - uaiCode: "26", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "8", - nom: "Grenoble", - }, - }, - { - nom: "Eure", - code: "27", - uaiCode: "27", - region: { - code: "28", - nom: "Normandie", - }, - academie: { - code: "70", - nom: "Normandie", - }, - }, - { - nom: "Eure-et-Loir", - code: "28", - uaiCode: "28", - region: { - code: "24", - nom: "Centre-Val de Loire", - }, - academie: { - code: "18", - nom: "Orléans-Tours", - }, - }, - { - nom: "Finistère", - code: "29", - uaiCode: "29", - region: { - code: "53", - nom: "Bretagne", - }, - academie: { - code: "14", - nom: "Rennes", - }, - }, - { - nom: "Corse-du-Sud", - code: "2A", - uaiCode: "620", - region: { - code: "94", - nom: "Corse", - }, - academie: { - code: "27", - nom: "Corse", - }, - }, - { - nom: "Haute-Corse", - code: "2B", - uaiCode: "720", - region: { - code: "94", - nom: "Corse", - }, - academie: { - code: "27", - nom: "Corse", - }, - }, - { - nom: "Gard", - code: "30", - uaiCode: "30", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "11", - nom: "Montpellier", - }, - }, - { - nom: "Haute-Garonne", - code: "31", - uaiCode: "31", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Gers", - code: "32", - uaiCode: "32", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Gironde", - code: "33", - uaiCode: "33", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "4", - nom: "Bordeaux", - }, - }, - { - nom: "Hérault", - code: "34", - uaiCode: "34", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "11", - nom: "Montpellier", - }, - }, - { - nom: "Ille-et-Vilaine", - code: "35", - uaiCode: "35", - region: { - code: "53", - nom: "Bretagne", - }, - academie: { - code: "14", - nom: "Rennes", - }, - }, - { - nom: "Indre", - code: "36", - uaiCode: "36", - region: { - code: "24", - nom: "Centre-Val de Loire", - }, - academie: { - code: "18", - nom: "Orléans-Tours", - }, - }, - { - nom: "Indre-et-Loire", - code: "37", - uaiCode: "37", - region: { - code: "24", - nom: "Centre-Val de Loire", - }, - academie: { - code: "18", - nom: "Orléans-Tours", - }, - }, - { - nom: "Isère", - code: "38", - uaiCode: "38", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "8", - nom: "Grenoble", - }, - }, - { - nom: "Jura", - code: "39", - uaiCode: "39", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "3", - nom: "Besançon", - }, - }, - { - nom: "Landes", - code: "40", - uaiCode: "40", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "4", - nom: "Bordeaux", - }, - }, - { - nom: "Loir-et-Cher", - code: "41", - uaiCode: "41", - region: { - code: "24", - nom: "Centre-Val de Loire", - }, - academie: { - code: "18", - nom: "Orléans-Tours", - }, - }, - { - nom: "Loire", - code: "42", - uaiCode: "42", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "10", - nom: "Lyon", - }, - }, - { - nom: "Haute-Loire", - code: "43", - uaiCode: "43", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "6", - nom: "Clermont-Ferrand", - }, - }, - { - nom: "Loire-Atlantique", - code: "44", - uaiCode: "44", - region: { - code: "52", - nom: "Pays de la Loire", - }, - academie: { - code: "17", - nom: "Nantes", - }, - }, - { - nom: "Loiret", - code: "45", - uaiCode: "45", - region: { - code: "24", - nom: "Centre-Val de Loire", - }, - academie: { - code: "18", - nom: "Orléans-Tours", - }, - }, - { - nom: "Lot", - code: "46", - uaiCode: "46", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Lot-et-Garonne", - code: "47", - uaiCode: "47", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "4", - nom: "Bordeaux", - }, - }, - { - nom: "Lozère", - code: "48", - uaiCode: "48", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "11", - nom: "Montpellier", - }, - }, - { - nom: "Maine-et-Loire", - code: "49", - uaiCode: "49", - region: { - code: "52", - nom: "Pays de la Loire", - }, - academie: { - code: "17", - nom: "Nantes", - }, - }, - { - nom: "Manche", - code: "50", - uaiCode: "50", - region: { - code: "28", - nom: "Normandie", - }, - academie: { - code: "70", - nom: "Normandie", - }, - }, - { - nom: "Marne", - code: "51", - uaiCode: "51", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "19", - nom: "Reims", - }, - }, - { - nom: "Haute-Marne", - code: "52", - uaiCode: "52", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "19", - nom: "Reims", - }, - }, - { - nom: "Mayenne", - code: "53", - uaiCode: "53", - region: { - code: "52", - nom: "Pays de la Loire", - }, - academie: { - code: "17", - nom: "Nantes", - }, - }, - { - nom: "Meurthe-et-Moselle", - code: "54", - uaiCode: "54", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "12", - nom: "Nancy-Metz", - }, - }, - { - nom: "Meuse", - code: "55", - uaiCode: "55", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "12", - nom: "Nancy-Metz", - }, - }, - { - nom: "Morbihan", - code: "56", - uaiCode: "56", - region: { - code: "53", - nom: "Bretagne", - }, - academie: { - code: "14", - nom: "Rennes", - }, - }, - { - nom: "Moselle", - code: "57", - uaiCode: "57", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "12", - nom: "Nancy-Metz", - }, - }, - { - nom: "Nièvre", - code: "58", - uaiCode: "58", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "7", - nom: "Dijon", - }, - }, - { - nom: "Nord", - code: "59", - uaiCode: "59", - region: { - code: "32", - nom: "Hauts-de-France", - }, - academie: { - code: "9", - nom: "Lille", - }, - }, - { - nom: "Oise", - code: "60", - uaiCode: "60", - region: { - code: "32", - nom: "Hauts-de-France", - }, - academie: { - code: "20", - nom: "Amiens", - }, - }, - { - nom: "Orne", - code: "61", - uaiCode: "61", - region: { - code: "28", - nom: "Normandie", - }, - academie: { - code: "70", - nom: "Normandie", - }, - }, - { - nom: "Pas-de-Calais", - code: "62", - uaiCode: "62", - region: { - code: "32", - nom: "Hauts-de-France", - }, - academie: { - code: "9", - nom: "Lille", - }, - }, - { - nom: "Puy-de-Dôme", - code: "63", - uaiCode: "63", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "6", - nom: "Clermont-Ferrand", - }, - }, - { - nom: "Pyrénées-Atlantiques", - code: "64", - uaiCode: "64", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "4", - nom: "Bordeaux", - }, - }, - { - nom: "Hautes-Pyrénées", - code: "65", - uaiCode: "65", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Pyrénées-Orientales", - code: "66", - uaiCode: "66", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "11", - nom: "Montpellier", - }, - }, - { - nom: "Bas-Rhin", - code: "67", - uaiCode: "67", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "15", - nom: "Strasbourg", - }, - }, - { - nom: "Haut-Rhin", - code: "68", - uaiCode: "68", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "15", - nom: "Strasbourg", - }, - }, - { - nom: "Rhône", - code: "69", - uaiCode: "69", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "10", - nom: "Lyon", - }, - }, - { - nom: "Haute-Saône", - code: "70", - uaiCode: "70", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "3", - nom: "Besançon", - }, - }, - { - nom: "Saône-et-Loire", - code: "71", - uaiCode: "71", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "7", - nom: "Dijon", - }, - }, - { - nom: "Sarthe", - code: "72", - uaiCode: "72", - region: { - code: "52", - nom: "Pays de la Loire", - }, - academie: { - code: "17", - nom: "Nantes", - }, - }, - { - nom: "Savoie", - code: "73", - uaiCode: "73", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "8", - nom: "Grenoble", - }, - }, - { - nom: "Haute-Savoie", - code: "74", - uaiCode: "74", - region: { - code: "84", - nom: "Auvergne-Rhône-Alpes", - }, - academie: { - code: "8", - nom: "Grenoble", - }, - }, - { - nom: "Paris", - code: "75", - uaiCode: "75", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "1", - nom: "Paris", - }, - }, - { - nom: "Seine-Maritime", - code: "76", - uaiCode: "76", - region: { - code: "28", - nom: "Normandie", - }, - academie: { - code: "70", - nom: "Normandie", - }, - }, - { - nom: "Seine-et-Marne", - code: "77", - uaiCode: "77", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "24", - nom: "Créteil", - }, - }, - { - nom: "Yvelines", - code: "78", - uaiCode: "78", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "25", - nom: "Versailles", - }, - }, - { - nom: "Deux-Sèvres", - code: "79", - uaiCode: "79", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "13", - nom: "Poitiers", - }, - }, - { - nom: "Somme", - code: "80", - uaiCode: "80", - region: { - code: "32", - nom: "Hauts-de-France", - }, - academie: { - code: "20", - nom: "Amiens", - }, - }, - { - nom: "Tarn", - code: "81", - uaiCode: "81", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Tarn-et-Garonne", - code: "82", - uaiCode: "82", - region: { - code: "76", - nom: "Occitanie", - }, - academie: { - code: "16", - nom: "Toulouse", - }, - }, - { - nom: "Var", - code: "83", - uaiCode: "83", - region: { - code: "93", - nom: "Provence-Alpes-Côte d'Azur", - }, - academie: { - code: "23", - nom: "Nice", - }, - }, - { - nom: "Vaucluse", - code: "84", - uaiCode: "84", - region: { - code: "93", - nom: "Provence-Alpes-Côte d'Azur", - }, - academie: { - code: "2", - nom: "Aix-Marseille", - }, - }, - { - nom: "Vendée", - code: "85", - uaiCode: "85", - region: { - code: "52", - nom: "Pays de la Loire", - }, - academie: { - code: "17", - nom: "Nantes", - }, - }, - { - nom: "Vienne", - code: "86", - uaiCode: "86", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "13", - nom: "Poitiers", - }, - }, - { - nom: "Haute-Vienne", - code: "87", - uaiCode: "87", - region: { - code: "75", - nom: "Nouvelle-Aquitaine", - }, - academie: { - code: "22", - nom: "Limoges", - }, - }, - { - nom: "Vosges", - code: "88", - uaiCode: "88", - region: { - code: "44", - nom: "Grand Est", - }, - academie: { - code: "12", - nom: "Nancy-Metz", - }, - }, - { - nom: "Yonne", - code: "89", - uaiCode: "89", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "7", - nom: "Dijon", - }, - }, - { - nom: "Territoire de Belfort", - code: "90", - uaiCode: "90", - region: { - code: "27", - nom: "Bourgogne-Franche-Comté", - }, - academie: { - code: "3", - nom: "Besançon", - }, - }, - { - nom: "Essonne", - code: "91", - uaiCode: "91", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "25", - nom: "Versailles", - }, - }, - { - nom: "Hauts-de-Seine", - code: "92", - uaiCode: "92", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "25", - nom: "Versailles", - }, - }, - { - nom: "Seine-Saint-Denis", - code: "93", - uaiCode: "93", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "24", - nom: "Créteil", - }, - }, - { - nom: "Val-de-Marne", - code: "94", - uaiCode: "94", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "24", - nom: "Créteil", - }, - }, - { - nom: "Val-d'Oise", - code: "95", - uaiCode: "95", - region: { - code: "11", - nom: "Île-de-France", - }, - academie: { - code: "25", - nom: "Versailles", - }, - }, - { - nom: "Guadeloupe", - code: "971", - uaiCode: "971", - region: { - code: "01", - nom: "Guadeloupe", - }, - academie: { - code: "32", - nom: "Guadeloupe", - }, - }, - { - nom: "Martinique", - code: "972", - uaiCode: "972", - region: { - code: "02", - nom: "Martinique", - }, - academie: { - code: "31", - nom: "Martinique", - }, - }, - { - nom: "Guyane", - code: "973", - uaiCode: "973", - region: { - code: "03", - nom: "Guyane", - }, - academie: { - code: "33", - nom: "Guyane", - }, - }, - { - nom: "La Réunion", - code: "974", - uaiCode: "974", - region: { - code: "04", - nom: "La Réunion", - }, - academie: { - code: "28", - nom: "La Réunion", - }, - }, - { - nom: "Mayotte", - code: "976", - uaiCode: "976", - region: { - code: "06", - nom: "Mayotte", - }, - academie: { - code: "43", - nom: "Mayotte", - }, - }, - { - nom: "Saint-Barthelemy", - code: "977", - uaiCode: "977", - region: { - code: "01", - nom: "Guadeloupe", - }, - academie: { - code: "32", - nom: "Guadeloupe", - }, - }, - { - nom: "Saint-Martin", - code: "978", - uaiCode: "978", - region: { - code: "01", - nom: "Guadeloupe", - }, - academie: { - code: "32", - nom: "Guadeloupe", - }, - }, - { - nom: "Terres australes et antarctique", - code: "984", - uaiCode: "984", - region: { - // TODO - code: "01", - nom: "Guadeloupe", - }, - academie: { - // TODO - code: "32", - nom: "Guadeloupe", - }, - }, - { - nom: "Wallis et Futuna", - code: "986", - uaiCode: "986", - region: { - code: "02", - nom: "Martinique", - }, - academie: { - code: "31", - nom: "Martinique", - }, - }, - { - nom: "Polynésie française", - code: "987", - uaiCode: "987", - region: { - // TODO - code: "01", - nom: "Guadeloupe", - }, - academie: { - // TODO - code: "32", - nom: "Guadeloupe", - }, - }, - { - nom: "Nouvelle Calédonie", - code: "988", - uaiCode: "988", - region: { - // TODO - code: "01", - nom: "Guadeloupe", - }, - academie: { - // TODO - code: "32", - nom: "Guadeloupe", - }, - }, - { - nom: "Ile de Clipperton", - code: "989", - uaiCode: "989", - region: { - // TODO - code: "01", - nom: "Guadeloupe", - }, - academie: { - // TODO - code: "32", - nom: "Guadeloupe", - }, - }, -]; - -export const DEPARTEMENTS_BY_ID = DEPARTEMENTS.reduce((acc, departement) => { - acc[departement.code] = departement; - return acc; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -}, {} as any); - -/** - * TODO Rationaliser / construire le référentiel des académies - */ -export const ACADEMIES = { - "01": { nom: "Paris", code: 1 }, - "02": { nom: "Aix-Marseille", code: 2 }, - "03": { nom: "Besançon", code: 3 }, - "04": { nom: "Bordeaux", code: 4 }, - "06": { nom: "Clermont-Ferrand", code: 6 }, - "07": { nom: "Dijon", code: 7 }, - "08": { nom: "Grenoble", code: 8 }, - "09": { nom: "Lille", code: 9 }, - 10: { nom: "Lyon", code: 10 }, - 11: { nom: "Montpellier", code: 11 }, - 12: { nom: "Nancy-Metz", code: 12 }, - 13: { nom: "Poitiers", code: 13 }, - 14: { nom: "Rennes", code: 14 }, - 15: { nom: "Strasbourg", code: 15 }, - 16: { nom: "Toulouse", code: 16 }, - 17: { nom: "Nantes", code: 17 }, - 18: { nom: "Orléans-Tours", code: 18 }, - 19: { nom: "Reims", code: 19 }, - 20: { nom: "Amiens", code: 20 }, - 22: { nom: "Limoges", code: 22 }, - 23: { nom: "Nice", code: 23 }, - 24: { nom: "Créteil", code: 24 }, - 25: { nom: "Versailles", code: 25 }, - 27: { nom: "Corse", code: 27 }, - 28: { nom: "La Réunion", code: 28 }, - 31: { nom: "Martinique", code: 31 }, - 32: { nom: "Guadeloupe", code: 32 }, - 33: { nom: "Guyane", code: 33 }, - 43: { nom: "Mayotte", code: 43 }, - 70: { nom: "Normandie", code: 70 }, - 77: { nom: "Saint-Barthélemy", code: 77 }, - 78: { nom: "Saint-Martin", code: 78 }, -}; - -export const ACADEMIES_BY_ID = Object.values(ACADEMIES).reduce( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (acc: any, academie) => { - acc[academie.code] = academie; - return acc; - } -); diff --git a/shared/constants/typeVoie.ts b/shared/constants/typeVoie.ts deleted file mode 100644 index 9efacce..0000000 --- a/shared/constants/typeVoie.ts +++ /dev/null @@ -1,47 +0,0 @@ -const typeVoie = [ - { code: "ALL", libelle: "Allée" }, - { code: "AV", libelle: "Avenue" }, - { code: "BD", libelle: "Boulevard" }, - { code: "CAR", libelle: "Carrefour" }, - { code: "CHE", libelle: "Chemin" }, - { code: "CHS", libelle: "Chaussée" }, - { code: "CITE", libelle: "Cité" }, - { code: "COR", libelle: "Corniche" }, - { code: "CRS", libelle: "Cours" }, - { code: "DOM", libelle: "Domaine" }, - { code: "DSC", libelle: "Descente" }, - { code: "ECA", libelle: "Ecart" }, - { code: "ESP", libelle: "Esplanade" }, - { code: "FG", libelle: "Faubourg" }, - { code: "GR", libelle: "Grande Rue" }, - { code: "HAM", libelle: "Hameau" }, - { code: "HLE", libelle: "Halle" }, - { code: "IMP", libelle: "Impasse" }, - { code: "LD", libelle: "Lieu-dit" }, - { code: "LOT", libelle: "Lotissement" }, - { code: "MAR", libelle: "Marché" }, - { code: "MTE", libelle: "Montée" }, - { code: "PAS", libelle: "Passage" }, - { code: "PL", libelle: "Place" }, - { code: "PLN", libelle: "Plaine" }, - { code: "PLT", libelle: "Plateau" }, - { code: "PRO", libelle: "Promenade" }, - { code: "PRV", libelle: "Parvis" }, - { code: "QUA", libelle: "Quartier" }, - { code: "QUAI", libelle: "Quai" }, - { code: "RES", libelle: "Résidence" }, - { code: "RLE", libelle: "Ruelle" }, - { code: "ROC", libelle: "Rocade" }, - { code: "RPT", libelle: "Rond-point" }, - { code: "RTE", libelle: "Route" }, - { code: "RUE", libelle: "Rue" }, - { code: "SEN", libelle: "Sente - Sentier" }, - { code: "SEN", libelle: "Sentier" }, - { code: "SQ", libelle: "Square" }, - { code: "TPL", libelle: "Terre-plein" }, - { code: "TRA", libelle: "Traverse" }, - { code: "VLA", libelle: "Villa" }, - { code: "VLGE", libelle: "Village" }, -] as const; - -export default typeVoie; diff --git a/shared/helpers/cerfa/domains/common/indiceRepetitionOptions.ts b/shared/helpers/cerfa/domains/common/indiceRepetitionOptions.ts deleted file mode 100644 index 87f51b1..0000000 --- a/shared/helpers/cerfa/domains/common/indiceRepetitionOptions.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const INDICE_DE_REPETITION_OPTIONS = [ - { - value: "B", - label: "Bis", - }, - { - value: "T", - label: "Ter", - }, - { - value: "Q", - label: "Quater", - }, - { - value: "C", - label: "Quinquiès", - }, -]; diff --git a/shared/helpers/cerfa/types/cerfa.types.ts b/shared/helpers/cerfa/types/cerfa.types.ts index 76e0a58..5dc9279 100644 --- a/shared/helpers/cerfa/types/cerfa.types.ts +++ b/shared/helpers/cerfa/types/cerfa.types.ts @@ -1,13 +1,4 @@ -export type FieldType = - | "text" - | "number" - | "select" - | "radio" - | "email" - | "date" - | "numberStepper" - | "consent" - | "phone"; +type FieldType = "text" | "number" | "select" | "radio" | "email" | "date" | "numberStepper" | "consent" | "phone"; export enum FieldEnum { "text" = "text", @@ -36,7 +27,7 @@ export interface RadioOption { value: string | number; } -export type SelectOptions = SelectOption[] | SelectNestedOption[] | RadioOption[]; +type SelectOptions = SelectOption[] | SelectNestedOption[] | RadioOption[]; export interface InformationMessage { type: "assistive" | "regulatory" | "bonus"; diff --git a/shared/helpers/common.ts b/shared/helpers/common.ts deleted file mode 100644 index bb55b68..0000000 --- a/shared/helpers/common.ts +++ /dev/null @@ -1 +0,0 @@ -export const getSirenFromSiret = (siret: string) => siret.substring(0, 9); diff --git a/shared/package.json b/shared/package.json index ecf46ef..769e646 100644 --- a/shared/package.json +++ b/shared/package.json @@ -15,13 +15,11 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "lodash-es": "^4.17.21", - "react": "18.2.0", + "date-fns": "^2.30.0", "type-fest": "^4.2.0", "zod": "^3.22.1" }, "devDependencies": { - "bson": "^5.4.0", "typescript": "^5.1.6", "zod": "^3.22.1" } diff --git a/shared/routes/common.routes.ts b/shared/routes/common.routes.ts index fcb436b..3ff5500 100644 --- a/shared/routes/common.routes.ts +++ b/shared/routes/common.routes.ts @@ -11,28 +11,9 @@ export const ZResError = z }) .strict(); -export const ZResOk = z.object({}).strict(); - export type IResError = z.input; export type IResErrorJson = Jsonify>; -export const ZReqParamsSearchPagination = z - .object({ - page: z.preprocess((v) => parseInt(v as string, 10), z.number().positive().optional()), - limit: z.preprocess((v) => parseInt(v as string, 10), z.number().positive().optional()), - q: z.string().optional(), - }) - .strict(); -export type IReqParamsSearchPagination = z.input; - -export const ZReqHeadersAuthorization = z - .object({ - Authorization: z.string().describe("Bearer token").optional(), - }) - .passthrough(); - -export type AuthStrategy = "api-key" | "cookie-session" | "access-token"; - interface IRouteSchemaCommon { path: string; querystring?: AnyZodObject; diff --git a/shared/security/permissions.ts b/shared/security/permissions.ts deleted file mode 100644 index 7c82e98..0000000 --- a/shared/security/permissions.ts +++ /dev/null @@ -1,36 +0,0 @@ -export type Permission = "admin" | "user:manage"; - -export type RoleNames = "none" | "admin"; - -export interface Role { - name: RoleNames; - permissions: Permission[]; -} - -export const NoneRole = { - name: "none", - permissions: [], -} satisfies Role; - -export const AdminRole = { - name: "admin", - permissions: ["admin", "user:manage"], -} satisfies Role; - -export type AccessPermission = Permission; - -export type AccessResourcePath = { - type: "params" | "query"; - key: string; -}; - -export type AccessRessouces = { - user?: ReadonlyArray<{ - _id: AccessResourcePath; - }>; -}; - -export type UserWithType = Readonly<{ - type: T; - value: V; -}>; diff --git a/shared/utils/assertUnreachable.ts b/shared/utils/assertUnreachable.ts deleted file mode 100644 index f506186..0000000 --- a/shared/utils/assertUnreachable.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function assertUnreachable(_x: never): never { - throw new Error("Didn't expect to get here"); -} diff --git a/shared/utils/index.ts b/shared/utils/index.ts deleted file mode 100644 index 16e6b59..0000000 --- a/shared/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./assertUnreachable"; diff --git a/ui/app/(application)/cerfa/components/CheckEmptyFields.tsx b/ui/app/(application)/cerfa/components/CheckEmptyFields.tsx index 4883ecb..75f8618 100644 --- a/ui/app/(application)/cerfa/components/CheckEmptyFields.tsx +++ b/ui/app/(application)/cerfa/components/CheckEmptyFields.tsx @@ -2,7 +2,7 @@ import { fr } from "@codegouvfr/react-dsfr"; import Alert from "@codegouvfr/react-dsfr/Alert"; import Button from "@codegouvfr/react-dsfr/Button"; import { Box, Typography } from "@mui/material"; -import { get } from "lodash"; +import { get } from "lodash-es"; import { FC, useState } from "react"; import { FieldError, useFormContext } from "react-hook-form"; diff --git a/ui/app/(application)/cerfa/components/blocks/contrat/domain/buildRemuneration.ts b/ui/app/(application)/cerfa/components/blocks/contrat/domain/buildRemuneration.ts deleted file mode 100644 index ffa8f69..0000000 --- a/ui/app/(application)/cerfa/components/blocks/contrat/domain/buildRemuneration.ts +++ /dev/null @@ -1,667 +0,0 @@ -import { addYears, format, formatISO, getMonth, getYear, isBefore, setDate, setMonth, subDays } from "date-fns"; -import { customParseISODate } from "shared/helpers/cerfa/utils/dates"; -const LATEST_SMIC_YEAR = 2022; - -const SMICs = { - 2022: { - smics: [ - { - annee: 2022, - mensuel: 1645.58, - horaire: 10.85, - heuresHebdomadaires: 35, - minimumGaranti: 3.86, - dateEntreeEnVigueur: "01/05/2022", - dateEntreeEnVigueurObj: customParseISODate("01/05/2022"), - dateParutionJo: "20/04/2022", - dateParutionJoObj: customParseISODate("20/04/2022"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1242.15, - horaire: 8.19, - heuresHebdomadaires: 35, - }, - }, - }, - { - annee: 2022, - mensuel: 1603.12, - horaire: 10.57, - heuresHebdomadaires: 35, - minimumGaranti: 3.76, - dateEntreeEnVigueur: "01/01/2022", - dateEntreeEnVigueurObj: customParseISODate("01/01/2022"), - dateParutionJo: "22/12/2021", - dateParutionJoObj: customParseISODate("22/12/2021"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1210.3, - horaire: 7.98, - heuresHebdomadaires: 35, - }, - }, - }, - ], - }, - 2021: { - smics: [ - { - annee: 2021, - mensuel: 1589.47, - horaire: 10.48, - heuresHebdomadaires: 35, - minimumGaranti: 3.73, - dateEntreeEnVigueur: "01/10/2021", - dateEntreeEnVigueurObj: customParseISODate("01/10/2021"), - dateParutionJo: "30/09/2021", - dateParutionJoObj: customParseISODate("30/09/2021"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1199.08, - horaire: 7.91, - heuresHebdomadaires: 35, - }, - }, - }, - { - annee: 2021, - mensuel: 1554.58, - horaire: 10.25, - heuresHebdomadaires: 35, - minimumGaranti: 3.65, - dateEntreeEnVigueur: "01/01/2021", - dateEntreeEnVigueurObj: customParseISODate("01/01/2021"), - dateParutionJo: "17/12/2020", - dateParutionJoObj: customParseISODate("17/12/2020"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1173.27, - horaire: 7.74, - heuresHebdomadaires: 35, - }, - }, - }, - ], - }, - 2020: { - smics: [ - { - annee: 2020, - mensuel: 1539.42, - horaire: 10.15, - heuresHebdomadaires: 35, - minimumGaranti: 3.65, - dateEntreeEnVigueur: "01/01/2020", - dateEntreeEnVigueurObj: customParseISODate("01/01/2020"), - dateParutionJo: "19/12/2019", - dateParutionJoObj: customParseISODate("19/12/2019"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1161.77, - horaire: 7.66, - heuresHebdomadaires: 35, - }, - }, - }, - ], - }, - 2019: { - smics: [ - { - annee: 2019, - mensuel: 1521.22, - horaire: 10.03, - heuresHebdomadaires: 35, - minimumGaranti: 3.62, - dateEntreeEnVigueur: "01/01/2019", - dateEntreeEnVigueurObj: customParseISODate("01/01/2019"), - dateParutionJo: "20/12/2018", - dateParutionJoObj: customParseISODate("20/12/2018"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1148.12, - horaire: 7.57, - heuresHebdomadaires: 35, - }, - }, - }, - ], - }, - 2018: { - smics: [ - { - annee: 2018, - mensuel: 1498.47, - horaire: 9.88, - heuresHebdomadaires: 35, - minimumGaranti: 3.57, - dateEntreeEnVigueur: "01/01/2018", - dateEntreeEnVigueurObj: customParseISODate("01/01/2018"), - dateParutionJo: "21/12/2017", - dateParutionJoObj: customParseISODate("21/12/2017"), - exceptions: { - 976: { - departement: 976, - nomDepartement: "Mayotte", - mensuel: 1131.43, // 1260.74 - horaire: 7.46, - heuresHebdomadaires: 35, // 39 - }, - }, - }, - ], - }, -}; - -const findSmicAtDate = (lookupDate: Date) => { - const lookupYear = lookupDate.getFullYear() as keyof typeof SMICs; - - if (!SMICs[lookupYear]) { - return SMICs[LATEST_SMIC_YEAR].smics[0]; // latest smic - } - - const smicsArray = SMICs[lookupYear].smics; - - return smicsArray.find((smicObj) => isBefore(lookupDate, smicObj.dateEntreeEnVigueurObj)) ?? smicsArray[0]; -}; - -const ceilUp = (x: number) => Math.ceil(x * 100) / 100; - -export const buildRemuneration = (data: any) => { - const selectedTaux = data.selectedTaux ?? {}; - const dateDebutContrat = customParseISODate(data.dateDebutContrat); - const dateFinContrat = customParseISODate(data.dateFinContrat); - const apprentiDateNaissance = customParseISODate(data.apprentiDateNaissance); - const isAnniversaireInLastMonth = getMonth(dateFinContrat) === getMonth(apprentiDateNaissance); - - const dateFinA1 = subDays(addYears(dateDebutContrat, 1), 1); - const dateDebutA2 = addYears(dateDebutContrat, 1); - const dateFinA2 = subDays(addYears(dateDebutA2, 1), 1); - const dateDebutA3 = addYears(dateDebutA2, 1); - const dateFinA3 = subDays(addYears(dateDebutA3, 1), 1); - const dateDebutA4 = addYears(dateDebutA3, 1); - - const ageA1 = Math.floor(data.apprentiAge); - const anniversaireA1 = addYears(apprentiDateNaissance, ageA1 + 1); - const ageA2 = ageA1 + 1; - const anniversaireA2 = addYears(anniversaireA1, 1); - const ageA3 = ageA2 + 1; - const anniversaireA3 = addYears(anniversaireA2, 1); - const ageA4 = ageA3 + 1; - const anniversaireA4 = addYears(anniversaireA3, 1); - const ageA5 = ageA4 + 1; - - // Kept for debug - // console.log([ - // { date: apprentiDateNaissance.toFormat("yyyy-MM-dd"), age: ageA1 }, - // { date: anniversaireA1.toFormat("yyyy-MM-dd"), age: ageA2 }, - // { date: anniversaireA2.toFormat("yyyy-MM-dd"), age: ageA3 }, - // { date: anniversaireA3.toFormat("yyyy-MM-dd"), age: ageA4 }, - // ]); - - const smicObj = findSmicAtDate(dateDebutContrat); - let SMIC = smicObj.mensuel; - const departementEmployeur = data.employeurAdresseDepartement; - let isSmicException = false; - // @ts-ignore - if (smicObj.exceptions && smicObj.exceptions[departementEmployeur]) { - // @ts-ignore - SMIC = smicObj.exceptions[departementEmployeur].mensuel; - isSmicException = true; - } - - const seuils = [17, 18, 21, 26]; - const getSeuils = (age: number) => { - if (age <= seuils[0]) return 0; - if (age >= seuils[1] && age < seuils[2]) return 1; - if (age >= seuils[2] && age < seuils[3]) return 2; - if (age >= seuils[3]) return 3; - return 0; - }; - - const taux = { - a1: { - 0: 27, - 1: 43, - 2: 53, - 3: 100, - }, - a2: { - 0: 39, - 1: 51, - 2: 61, - 3: 100, - }, - a3: { - 0: 55, - 1: 67, - 2: 78, - 3: 100, - }, - a4: { - 0: 55, - 1: 67, - 2: 78, - 3: 100, - }, - }; - - const isChangingTaux = (currentAge: number, nextAge: number) => { - return getSeuils(nextAge) > getSeuils(currentAge); - }; - - const getTaux = (part: number, tauxValue: number) => Math.max(selectedTaux?.[part] ?? 0, tauxValue); - - let finRemuneration = false; - const emptyLineObj = { - dateDebut: "", - dateFin: "", - taux: 0, - tauxMinimal: 0, - typeSalaire: "SMIC", - salaireBrut: 0, - }; - - let result1 = { - 11: emptyLineObj, - 12: emptyLineObj, - }; - const taux11 = taux.a1[getSeuils(ageA1)]; - const taux12 = taux.a1[getSeuils(ageA2)]; - const selectedTaux11 = getTaux(1.1, taux11); - const selectedTaux12 = getTaux(1.2, taux12); - if (isChangingTaux(ageA1, ageA2) && !(isAnniversaireInLastMonth && getYear(dateFinContrat) === getYear(dateFinA1))) { - const anniversaireMonth = getMonth(anniversaireA1); - const dateDebut12 = setMonth(setDate(anniversaireA1, 1), anniversaireMonth + 1); - - const dateFin11 = subDays(dateDebut12, 1); - - if (dateFin11 >= dateFinContrat) { - finRemuneration = true; - result1 = { - 11: { - dateDebut: formatISO(dateDebutContrat), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux11, - tauxMinimal: taux11, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux11) / 100), - }, - 12: emptyLineObj, - }; - } else if (dateFinA1 >= dateFinContrat) { - finRemuneration = true; - result1 = { - 11: { - dateDebut: formatISO(dateDebutContrat), - dateFin: formatISO(dateFin11), - taux: selectedTaux11, - tauxMinimal: taux11, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux11) / 100), - }, - 12: { - dateDebut: formatISO(dateDebut12), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux12, - tauxMinimal: taux12, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux12) / 100), - }, - }; - } else { - result1 = { - 11: { - dateDebut: formatISO(dateDebutContrat), - dateFin: formatISO(dateFin11), - taux: selectedTaux11, - tauxMinimal: taux11, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux11) / 100), - }, - 12: { - dateDebut: formatISO(dateDebut12), - dateFin: formatISO(dateFinA1), - taux: selectedTaux12, - tauxMinimal: taux12, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux12) / 100), - }, - }; - } - } else { - if (dateFinA1 >= dateFinContrat) { - finRemuneration = true; - result1 = { - 11: { - dateDebut: formatISO(dateDebutContrat), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux11, - tauxMinimal: taux11, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux11) / 100), - }, - 12: emptyLineObj, - }; - } else { - result1 = { - 11: { - dateDebut: format(dateDebutContrat, "yyyy-MM-dd"), - dateFin: format(dateFinA1, "yyyy-MM-dd"), - taux: selectedTaux11, - tauxMinimal: taux11, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux11) / 100), - }, - 12: emptyLineObj, - }; - } - } - - let result2 = { - 21: emptyLineObj, - 22: emptyLineObj, - }; - - const taux21 = taux.a2[getSeuils(ageA2)]; - const taux22 = taux.a2[getSeuils(ageA3)]; - const selectedTaux21 = getTaux(2.1, taux21); - const selectedTaux22 = getTaux(2.2, taux22); - if ( - isChangingTaux(ageA2, ageA3) && - !finRemuneration && - !(isAnniversaireInLastMonth && getYear(dateFinContrat) === getYear(dateFinA2)) - ) { - const anniversaireA2Month = getMonth(anniversaireA2); - const dateDebut22 = setMonth(setDate(anniversaireA2, 1), anniversaireA2Month + 1); - const dateFin21 = subDays(dateDebut22, 1); - - if (dateFin21 >= dateFinContrat) { - finRemuneration = true; - result2 = { - 21: { - dateDebut: formatISO(dateDebutA2), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux21, - tauxMinimal: taux21, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux21) / 100), - }, - 22: emptyLineObj, - }; - } else if (dateFinA2 >= dateFinContrat) { - finRemuneration = true; - result2 = { - 21: { - dateDebut: formatISO(dateDebutA2), - dateFin: formatISO(dateFin21), - taux: selectedTaux21, - tauxMinimal: taux21, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux21) / 100), - }, - 22: { - dateDebut: formatISO(dateDebut22), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux22, - tauxMinimal: taux22, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux22) / 100), - }, - }; - } else { - result2 = { - 21: { - dateDebut: formatISO(dateDebutA2), - dateFin: formatISO(dateFin21), - taux: selectedTaux21, - tauxMinimal: taux21, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux21) / 100), - }, - 22: { - dateDebut: formatISO(dateDebut22), - dateFin: formatISO(dateFinA2), - taux: selectedTaux22, - tauxMinimal: taux22, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux22) / 100), - }, - }; - } - } else if (!finRemuneration) { - if (dateFinA2 >= dateFinContrat) { - finRemuneration = true; - result2 = { - 21: { - dateDebut: formatISO(dateDebutA2), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux21, - tauxMinimal: taux21, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux21) / 100), - }, - 22: emptyLineObj, - }; - } else { - result2 = { - 21: { - dateDebut: formatISO(dateDebutA2), - dateFin: formatISO(dateFinA2), - taux: selectedTaux21, - tauxMinimal: taux21, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux21) / 100), - }, - 22: emptyLineObj, - }; - } - } - - let result3 = { - 31: emptyLineObj, - 32: emptyLineObj, - }; - const taux31 = taux.a3[getSeuils(ageA3)]; - const taux32 = taux.a3[getSeuils(ageA4)]; - const selectedTaux31 = getTaux(3.1, taux31); - const selectedTaux32 = getTaux(3.2, taux32); - if ( - isChangingTaux(ageA3, ageA4) && - !finRemuneration && - !(isAnniversaireInLastMonth && getYear(dateFinContrat) === getYear(dateFinA3)) - ) { - const anniversaireA3Month = getMonth(anniversaireA3); - const dateDebut32 = setMonth(setDate(anniversaireA3, 1), anniversaireA3Month + 1); - const dateFin31 = subDays(dateDebut32, 1); - - if (dateFin31 >= dateFinContrat) { - finRemuneration = true; - result3 = { - 31: { - dateDebut: formatISO(dateDebutA3), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux31, - tauxMinimal: taux31, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux31) / 100), - }, - 32: emptyLineObj, - }; - } else if (dateFinA3 >= dateFinContrat) { - finRemuneration = true; - result3 = { - 31: { - dateDebut: formatISO(dateDebutA3), - dateFin: formatISO(dateFin31), - taux: selectedTaux31, - tauxMinimal: taux31, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux31) / 100), - }, - 32: { - dateDebut: formatISO(dateDebut32), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux32, - tauxMinimal: taux32, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux32) / 100), - }, - }; - } else { - result3 = { - 31: { - dateDebut: formatISO(dateDebutA3), - dateFin: formatISO(dateFin31), - taux: selectedTaux31, - tauxMinimal: taux31, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux31) / 100), - }, - 32: { - dateDebut: formatISO(dateDebut32), - dateFin: formatISO(dateFinA3), - taux: selectedTaux32, - tauxMinimal: taux32, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux32) / 100), - }, - }; - } - } else if (!finRemuneration) { - if (dateFinA3 >= dateFinContrat) { - finRemuneration = true; - result3 = { - 31: { - dateDebut: formatISO(dateDebutA3), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux31, - tauxMinimal: taux31, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux31) / 100), - }, - 32: emptyLineObj, - }; - } else { - result3 = { - 31: { - dateDebut: formatISO(dateDebutA3), - dateFin: formatISO(dateFinA3), - taux: selectedTaux31, - tauxMinimal: taux31, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux31) / 100), - }, - 32: emptyLineObj, - }; - } - } - - let result4 = { - 41: emptyLineObj, - 42: emptyLineObj, - }; - const taux41 = taux.a4[getSeuils(ageA4)]; - const taux42 = taux.a4[getSeuils(ageA5)]; - const selectedTaux41 = getTaux(4.1, taux41); - const selectedTaux42 = getTaux(4.2, taux42); - - if (isChangingTaux(ageA4, ageA5) && !finRemuneration && !isAnniversaireInLastMonth) { - const anniversaireA4Month = getMonth(anniversaireA4); - const dateDebut42 = setMonth(setDate(anniversaireA4, 1), anniversaireA4Month + 1); - const dateFin41 = subDays(dateDebut42, 1); - - if (dateFin41 >= dateFinContrat) { - finRemuneration = true; - result4 = { - 41: { - dateDebut: formatISO(dateDebutA4), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux41, - tauxMinimal: taux41, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux41) / 100), - }, - 42: emptyLineObj, - }; - } else { - result4 = { - 41: { - dateDebut: formatISO(dateDebutA4), - dateFin: formatISO(dateFin41), - taux: selectedTaux41, - tauxMinimal: taux41, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux41) / 100), - }, - 42: { - dateDebut: formatISO(dateDebut42), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux42, - tauxMinimal: taux42, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux42) / 100), - }, - }; - } - } else if (!finRemuneration) { - result4 = { - 41: { - dateDebut: formatISO(dateDebutA4), - dateFin: formatISO(dateFinContrat), - taux: selectedTaux41, - tauxMinimal: taux41, - typeSalaire: "SMIC", - salaireBrut: ceilUp((SMIC * selectedTaux41) / 100), - }, - 42: emptyLineObj, - }; - } - - const buildBlock2 = (part: any, result: any) => - result[part].taux - ? { - dateDebut: result[part].dateDebut, - dateFin: result[part].dateFin, - taux: result[part].taux, - tauxMinimal: result[part].tauxMinimal, - typeSalaire: result[part].typeSalaire, - salaireBrut: ceilUp(result[part].salaireBrut), - ordre: `${part.toString()[0]}.${part.toString()[1]}`, - } - : undefined; - - const remunerationsAnnuelles = [ - buildBlock2(11, result1), - buildBlock2(12, result1), - buildBlock2(21, result2), - buildBlock2(22, result2), - buildBlock2(31, result3), - buildBlock2(32, result3), - buildBlock2(41, result4), - buildBlock2(42, result4), - ].filter((item) => item); - - return { - remunerationsAnnuelles, - // @ts-ignore - salaireEmbauche: remunerationsAnnuelles?.[0].salaireBrut, - smicObj: { - ...smicObj, - isSmicException, - selectedSmic: SMIC, - }, - }; -}; diff --git a/ui/app/(application)/cerfa/controls/apprentiDateNaissance.control.ts b/ui/app/(application)/cerfa/controls/apprentiDateNaissance.control.ts index eae6553..e4514d5 100644 --- a/ui/app/(application)/cerfa/controls/apprentiDateNaissance.control.ts +++ b/ui/app/(application)/cerfa/controls/apprentiDateNaissance.control.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import { isEmpty } from "lodash-es"; import { CerfaControl, CerfaForm } from "shared/helpers/cerfa/types/cerfa.types"; export const apprentiDateNaissanceControl: CerfaControl[] = [ diff --git a/ui/app/(application)/cerfa/controls/apprentiNationalite.control.ts b/ui/app/(application)/cerfa/controls/apprentiNationalite.control.ts index 9454800..2dfa7d4 100644 --- a/ui/app/(application)/cerfa/controls/apprentiNationalite.control.ts +++ b/ui/app/(application)/cerfa/controls/apprentiNationalite.control.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import { isEmpty } from "lodash-es"; import { CerfaControl, InformationMessage } from "shared/helpers/cerfa/types/cerfa.types"; export const apprentiNationaliteControl: CerfaControl[] = [ diff --git a/ui/app/(application)/cerfa/controls/apprentiNir.control.ts b/ui/app/(application)/cerfa/controls/apprentiNir.control.ts index 1fa91d4..b5f26fd 100644 --- a/ui/app/(application)/cerfa/controls/apprentiNir.control.ts +++ b/ui/app/(application)/cerfa/controls/apprentiNir.control.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import { isEmpty } from "lodash-es"; import { CerfaControl } from "shared/helpers/cerfa/types/cerfa.types"; import { nirControl } from "./common/nir.control"; diff --git a/ui/app/(application)/cerfa/controls/apprentiSexe.control.ts b/ui/app/(application)/cerfa/controls/apprentiSexe.control.ts index 2da4b8c..1eb8960 100644 --- a/ui/app/(application)/cerfa/controls/apprentiSexe.control.ts +++ b/ui/app/(application)/cerfa/controls/apprentiSexe.control.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import { isEmpty } from "lodash-es"; import { CerfaControl } from "shared/helpers/cerfa/types/cerfa.types"; export const apprentiSexe: CerfaControl[] = [ diff --git a/ui/app/(application)/cerfa/controls/common/nir.control.ts b/ui/app/(application)/cerfa/controls/common/nir.control.ts index 446f79f..320fc02 100644 --- a/ui/app/(application)/cerfa/controls/common/nir.control.ts +++ b/ui/app/(application)/cerfa/controls/common/nir.control.ts @@ -1,4 +1,4 @@ -import { isEmpty } from "lodash"; +import { isEmpty } from "lodash-es"; import { ControlReturn } from "shared/helpers/cerfa/types/cerfa.types"; interface NirControlParams { diff --git a/ui/app/(application)/cerfa/controls/employeurSiret.control.ts b/ui/app/(application)/cerfa/controls/employeurSiret.control.ts index 00e94ca..fb2c6dc 100644 --- a/ui/app/(application)/cerfa/controls/employeurSiret.control.ts +++ b/ui/app/(application)/cerfa/controls/employeurSiret.control.ts @@ -27,7 +27,7 @@ const SUCCESS = { stateRelatedMessage: "Récupéré automatiquement à partir du siret", }; -export const employerSiretLogic: CerfaControl = { +const employerSiretLogic: CerfaControl = { deps: ["employeur.siret"], process: async ({ values, signal }) => { const siret = values.employeur.siret; diff --git a/ui/app/(application)/cerfa/controls/utils/api.utils.ts b/ui/app/(application)/cerfa/controls/utils/api.utils.ts index fd1d1dc..0863ca5 100644 --- a/ui/app/(application)/cerfa/controls/utils/api.utils.ts +++ b/ui/app/(application)/cerfa/controls/utils/api.utils.ts @@ -98,10 +98,3 @@ export const controlEmail = async (email: string): Promise<{ is_valid?: boolean; return { error: e.prettyMessage ?? "Une erreur technique est survenue" }; } }; - -export const apiService = { - fetchSiret, - fetchCodePostal, - fetchNaf, - fetchCfdrncp, -}; diff --git a/ui/app/(application)/cerfa/controls/utils/createCopyOrRestoreRule.ts b/ui/app/(application)/cerfa/controls/utils/createCopyOrRestoreRule.ts index fd13685..f2ad3c7 100644 --- a/ui/app/(application)/cerfa/controls/utils/createCopyOrRestoreRule.ts +++ b/ui/app/(application)/cerfa/controls/utils/createCopyOrRestoreRule.ts @@ -8,8 +8,6 @@ interface CreateCopyOrRestoreRuleParams { fieldNames?: string[]; } -type ControlGenerator = (params: CreateCopyOrRestoreRuleParams) => CerfaControl; - export const createCopyOrRestoreRule = ({ deps, restoreIf, @@ -47,36 +45,3 @@ export const createCopyOrRestoreRule = ({ }, }; }; - -export const createResetOrRestoreRule: ControlGenerator = ({ deps, restoreIf, fieldNames, useCache = true }) => { - return { - deps, - process: ({ values, cache, fields }) => { - const shouldRestore = restoreIf({ values }); - if (shouldRestore) { - const cascade = fieldNames?.reduce((acc, name) => { - const valueToRestore = useCache ? cache?.[name].value : undefined; - return { - ...acc, - [name]: { - value: valueToRestore, - reset: !valueToRestore, - }, - }; - }, {}); - return { cascade }; - } else { - const cascade = fieldNames?.reduce((acc, name) => { - return { - ...acc, - [name]: { - value: undefined, - reset: true, - }, - }; - }, {}); - return { cache: fields, cascade }; - } - }, - }; -}; diff --git a/ui/app/(application)/cerfa/utils/cerfa.utils.ts b/ui/app/(application)/cerfa/utils/cerfa.utils.ts index 0835729..1719261 100644 --- a/ui/app/(application)/cerfa/utils/cerfa.utils.ts +++ b/ui/app/(application)/cerfa/utils/cerfa.utils.ts @@ -16,7 +16,7 @@ export interface CerfaStep { messages?: InformationMessage[]; } -export type CerfaStepType = "EMPLOYEUR" | "APPRENTI" | "MAITRE_APPRENTISSAGE" | "CONTRAT" | "FORMATION" | "SIGNATURES"; +type CerfaStepType = "EMPLOYEUR" | "APPRENTI" | "MAITRE_APPRENTISSAGE" | "CONTRAT" | "FORMATION" | "SIGNATURES"; export const CERFA_STEPS: Record = { EMPLOYEUR: { diff --git a/ui/app/(application)/cerfa/utils/cerfaSchema.ts b/ui/app/(application)/cerfa/utils/cerfaSchema.ts index 613d1ad..b64e186 100644 --- a/ui/app/(application)/cerfa/utils/cerfaSchema.ts +++ b/ui/app/(application)/cerfa/utils/cerfaSchema.ts @@ -17,7 +17,7 @@ export const getFieldSchema = (name: string) => { return cerfaSchema.fields[name]; }; -export const indexedDependencies = (() => { +const indexedDependencies = (() => { const names: Record = {}; controls.forEach((rule) => { rule.deps.forEach((dep) => { diff --git a/ui/app/(application)/cerfa/utils/form.utils.ts b/ui/app/(application)/cerfa/utils/form.utils.ts index 5196dbe..3a63467 100644 --- a/ui/app/(application)/cerfa/utils/form.utils.ts +++ b/ui/app/(application)/cerfa/utils/form.utils.ts @@ -1,6 +1,6 @@ import { InputProps } from "@codegouvfr/react-dsfr/Input"; -import { get, setWith } from "lodash"; -import { FieldError, FieldErrorsImpl, FieldValues, FormState, Merge, UseFormReturn } from "react-hook-form"; +import { get } from "lodash-es"; +import { FieldValues, FormState, UseFormReturn } from "react-hook-form"; import { SetterOrUpdater } from "recoil"; import { CerfaField, CerfaForm, InformationMessage } from "shared/helpers/cerfa/types/cerfa.types"; @@ -80,18 +80,6 @@ export const validateField = async ( return error; }; -export const getValues = (fields: any) => { - if (!fields) return undefined; - const values = {}; - Object.entries(fields).forEach(([key, field]) => { - // @ts-expect-error: todo - setWith(values, key, field.value); - }); - return values; -}; - -export const isEmptyValue = (value: any) => value === "" || value === undefined || value === null; - export const downloadFile = (data: Blob, filename: string) => { // Step 5: Create a download link for the Blob const url = URL.createObjectURL(data); @@ -124,24 +112,3 @@ export const getInformationMessageMarginTop = (fieldSchema: CerfaField) => { return 4; } }; - -export const isFieldError = ( - error: FieldError | Merge> | undefined -): error is FieldError => { - if (!error) return false; - return "type" in error && "message" in error; -}; - -export const countBlockErrors = (errors: FormState["errors"]) => { - let count = 0; - - Object.entries(errors).forEach(([_, value]) => { - if (isFieldError(value as FieldError)) { - count++; - } else { - count += countBlockErrors(value as FormState["errors"]); - } - }); - - return count; -}; diff --git a/ui/components/SearchBar.tsx b/ui/components/SearchBar.tsx deleted file mode 100644 index 8eaa8d6..0000000 --- a/ui/components/SearchBar.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { SearchBar as DSFRSearchBar, SearchBarProps } from "@codegouvfr/react-dsfr/SearchBar"; -import { FC } from "react"; - -interface Props extends SearchBarProps { - defaultValue?: string; -} - -const SearchBar: FC = ({ defaultValue, ...rest }) => { - return } {...rest} />; -}; - -export default SearchBar; diff --git a/ui/components/ThemeProvider.tsx b/ui/components/ThemeProvider.tsx deleted file mode 100644 index f9ebfc7..0000000 --- a/ui/components/ThemeProvider.tsx +++ /dev/null @@ -1,4 +0,0 @@ -"use client"; -import MuiDsfrThemeProvider from "@codegouvfr/react-dsfr/mui"; - -export { MuiDsfrThemeProvider }; diff --git a/ui/components/form/ToggleSwitchInput.tsx b/ui/components/form/ToggleSwitchInput.tsx deleted file mode 100644 index f714064..0000000 --- a/ui/components/form/ToggleSwitchInput.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { ToggleSwitch, ToggleSwitchProps } from "@codegouvfr/react-dsfr/ToggleSwitch"; -import { Controller, ControllerProps, FieldValues } from "react-hook-form"; - -interface Props extends Omit, "render"> { - toggleSwitchProps: ToggleSwitchProps; -} - -const ToggleSwitchInput = ({ toggleSwitchProps, ...props }: Props) => { - return ( - - {...props} - render={({ field }) => { - return ( - { - return field.onChange(value); - }} - /> - ); - }} - /> - ); -}; - -export default ToggleSwitchInput; diff --git a/ui/components/form/input/Input.tsx b/ui/components/form/input/Input.tsx deleted file mode 100644 index 22c0966..0000000 --- a/ui/components/form/input/Input.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { fr } from "@codegouvfr/react-dsfr/fr"; -import { InputProps } from "@codegouvfr/react-dsfr/Input"; -import { cx } from "@codegouvfr/react-dsfr/tools/cx"; -import React, { forwardRef, memo, useId } from "react"; -import { symToStr } from "tsafe/symToStr"; - -import InputGroup from "./InputGroup"; - -/** - * @see - * This is a more composable version to make custom components - * */ -export const Input = memo( - forwardRef((props, ref) => { - const { - disabled = false, - iconId, - classes = {}, - state = "default", - textArea = false, - nativeTextAreaProps, - nativeInputProps, - ...rest - } = props; - - const nativeInputOrTextAreaProps = (textArea ? nativeTextAreaProps : nativeInputProps) ?? {}; - - const NativeInputOrTextArea = textArea ? "textarea" : "input"; - - const inputId = (function useClosure() { - const id = useId(); - - return nativeInputOrTextAreaProps.id ?? `input-${id}`; - })(); - - const messageId = `${inputId}-desc-error`; - - return ( - - {(() => { - const nativeInputOrTextArea = ( - { - switch (state) { - case "error": - return "fr-input--error"; - case "success": - return "fr-input--valid"; - case "default": - return undefined; - } - })() - ), - classes.nativeInputOrTextArea - )} - disabled={disabled || undefined} - aria-describedby={messageId} - type={textArea ? undefined : nativeInputProps?.type ?? "text"} - id={inputId} - /> - ); - - return iconId === undefined ? ( - nativeInputOrTextArea - ) : ( -
{nativeInputOrTextArea}
- ); - })()} -
- ); - }) -); - -Input.displayName = symToStr({ Input }); - -export default Input; diff --git a/ui/components/form/input/MaskInput.tsx b/ui/components/form/input/MaskInput.tsx index 1728035..fbb671d 100644 --- a/ui/components/form/input/MaskInput.tsx +++ b/ui/components/form/input/MaskInput.tsx @@ -15,7 +15,7 @@ interface Props extends InputProps.RegularInput { * @see * This is a more composable version to make custom components * */ -export const MaskInput = memo( +const MaskInput = memo( forwardRef((props, ref) => { const { disabled = false, diff --git a/ui/components/form/input/PhoneInput.tsx b/ui/components/form/input/PhoneInput.tsx index 5032ecb..20ea98b 100644 --- a/ui/components/form/input/PhoneInput.tsx +++ b/ui/components/form/input/PhoneInput.tsx @@ -15,7 +15,7 @@ interface Props extends InputProps.RegularInput { * @see * This is a more composable version to make custom components * */ -export const PhoneInput = memo( +const PhoneInput = memo( forwardRef((props, ref) => { const { disabled = false, diff --git a/ui/components/infoDetails/InfoDetails.tsx b/ui/components/infoDetails/InfoDetails.tsx deleted file mode 100644 index a7a692f..0000000 --- a/ui/components/infoDetails/InfoDetails.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Box, Grid, Typography } from "@mui/material"; -import React, { Fragment } from "react"; - -interface Props { - title?: string; - data: TData; - rows: { - [key: string]: { - header?: () => React.ReactNode; - cell?: (data: TData) => React.ReactNode; - }; - }; -} -/** - * A handy component to display a list of key/value pairs - * largely inspired by @tanstack/react-table - */ -const InfoDetails = ({ title, rows, data }: Props) => { - return ( - - {title && ( - - {title} - - )} - - {Object.entries(rows).map(([key, { header, cell }]) => { - const dataKey = key as keyof TData; - const value = data[dataKey]; - - return ( - - - {header?.() ?? key} - - - {/* @ts-ignore */} - {cell?.(data) ?? value} - - - ); - })} - - - ); -}; - -export default InfoDetails; diff --git a/ui/components/table/Table.tsx b/ui/components/table/Table.tsx deleted file mode 100644 index 26e3b2d..0000000 --- a/ui/components/table/Table.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Box } from "@mui/material"; -import { styled } from "@mui/material/styles"; -import { DataGrid, DataGridProps, frFR, GridValidRowModel } from "@mui/x-data-grid"; - -const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ - "& .MuiTablePagination-selectLabel": { - margin: theme.spacing(0), - }, -})); - -export const Table = (props: DataGridProps) => { - return ( - - row?._id ?? row.id} - rowHeight={60} - localeText={frFR.components.MuiDataGrid.defaultProps.localeText} - {...props} - /> - - ); -}; - -export default Table; diff --git a/ui/components/toast/Toast.tsx b/ui/components/toast/Toast.tsx deleted file mode 100644 index 503014b..0000000 --- a/ui/components/toast/Toast.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Alert, AlertProps, Snackbar, SnackbarProps } from "@mui/material"; -import { FC, useState } from "react"; - -interface Props extends SnackbarProps { - severity?: AlertProps["severity"]; - message?: string; - handleClose?: (event?: React.SyntheticEvent | Event, reason?: string) => void; -} - -interface UseToast { - severity: AlertProps["severity"]; - message: string; -} - -export const useToast = () => { - const [toast, setToast] = useState(); - - const handleClose = (event?: React.SyntheticEvent | Event, reason?: string) => { - if (reason === "clickaway") { - return; - } - - setToast(undefined); - }; - - return { toast, setToast, handleClose }; -}; - -const Toast: FC = ({ severity, message, handleClose, ...rest }) => { - return ( - - - {message} - - - ); -}; - -export default Toast; diff --git a/ui/config.public.ts b/ui/config.public.ts index 86cac04..40429ba 100644 --- a/ui/config.public.ts +++ b/ui/config.public.ts @@ -1,4 +1,4 @@ -export interface PublicConfig { +interface PublicConfig { sentry: { dsn: string; }; diff --git a/ui/icons/NotFound copy.tsx b/ui/icons/NotFound copy.tsx deleted file mode 100644 index 0eaa851..0000000 --- a/ui/icons/NotFound copy.tsx +++ /dev/null @@ -1,416 +0,0 @@ -import React, { FC } from "react"; - -export const NotFound: FC = () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); diff --git a/ui/package.json b/ui/package.json index ec8b540..486d2a2 100644 --- a/ui/package.json +++ b/ui/package.json @@ -17,10 +17,8 @@ "dependencies": { "@codegouvfr/react-dsfr": "^0.75.7", "@emotion/react": "^11.11.1", - "@emotion/server": "^11.11.0", "@emotion/styled": "^11.11.0", "@mui/material": "^5.14.8", - "@mui/x-data-grid": "^6.13.0", "@sentry/integrations": "^7.81.1", "@sentry/nextjs": "^7.64.0", "@tanstack/react-query": "^4.32.6", @@ -31,7 +29,6 @@ "lodash-es": "^4.17.21", "next": "^13.4.17", "next-plausible": "^3.10.2", - "notion-client": "^6.16.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.45.4", @@ -47,7 +44,6 @@ "zod": "^3.22.4" }, "devDependencies": { - "notion-types": "^6.16.0", "type-fest": "^4.2.0" } } diff --git a/ui/utils/api.utils.ts b/ui/utils/api.utils.ts index a16945b..e53a914 100644 --- a/ui/utils/api.utils.ts +++ b/ui/utils/api.utils.ts @@ -1,4 +1,4 @@ -import { IDeleteRoutes, IGetRoutes, IPostRoutes, IPutRoutes, IRequest, IResponse } from "shared"; +import { IPostRoutes, IRequest, IResponse } from "shared"; import { generateUri, PathParam, QueryString, WithQueryStringAndPathParam } from "shared/helpers/generateUri"; import { IResErrorJson, IRouteSchema, IRouteSchemaWrite } from "shared/routes/common.routes"; import { EmptyObject } from "type-fest"; @@ -81,7 +81,7 @@ export function generateUrl(path: string, options: WithQueryStringAndPathParam = return removeAtEnd(publicConfig.apiEndpoint, "/") + generateUri(path, { params, querystring }); } -export interface ApiErrorContext { +interface ApiErrorContext { path: string; params: PathParam; querystring: QueryString; @@ -166,48 +166,3 @@ export async function apiPost

( - path: P, - options: IRequest -): Promise> { - const { requestInit, headers } = await optionsToFetchParams("GET", options); - - const res = await fetch(generateUrl(path, options), requestInit); - - if (!res.ok) { - throw await ApiError.build(path, headers, options, res); - } - - return res.json(); -} - -export async function apiPut

( - path: P, - options: IRequest -): Promise> { - const { requestInit, headers } = await optionsToFetchParams("PUT", options); - - const res = await fetch(generateUrl(path, options), requestInit); - - if (!res.ok) { - throw await ApiError.build(path, headers, options, res); - } - - return res.json(); -} - -export async function apiDelete

( - path: P, - options: IRequest -): Promise> { - const { requestInit, headers } = await optionsToFetchParams("DELETE", options); - - const res = await fetch(generateUrl(path, options), requestInit); - - if (!res.ok) { - throw await ApiError.build(path, headers, options, res); - } - - return res.json(); -} diff --git a/ui/utils/date.utils.ts b/ui/utils/date.utils.ts index 5f4f7e5..8de9b00 100644 --- a/ui/utils/date.utils.ts +++ b/ui/utils/date.utils.ts @@ -2,19 +2,6 @@ import { format } from "date-fns"; import fr from "date-fns/locale/fr"; import { customParseISODate } from "shared/helpers/cerfa/utils/dates"; -export const prettyPrintDate = (date: string) => { - const event = new Date(date); - const options = { - hour: "2-digit" as const, - minute: "2-digit" as const, - year: "numeric" as const, - month: "short" as const, - day: "numeric" as const, - }; - - return event.toLocaleDateString("fr-FR", options); -}; - export const formatDate = (date: string, dateFormat = "dd/MM/yyyy") => { return format(customParseISODate(date), dateFormat, { locale: fr, diff --git a/ui/utils/query.utils.ts b/ui/utils/query.utils.ts index 0a5fcae..0246751 100644 --- a/ui/utils/query.utils.ts +++ b/ui/utils/query.utils.ts @@ -1,5 +1,4 @@ import { QueryClient } from "@tanstack/react-query"; -import { ReadonlyURLSearchParams } from "next/navigation"; const QUERY_CLIENT_RETRY_DELAY = 3000; const QUERY_CLIENT_RETRY_ATTEMPTS = 1; @@ -14,31 +13,3 @@ export const queryClient = new QueryClient({ }, }, }); - -export const getSearchParamsForQuery = (searchParams: ReadonlyURLSearchParams | null) => { - const q = searchParams?.get("q") ?? ""; - const page = searchParams?.get("page") ?? "1"; - const limit = searchParams?.get("limit") ?? "10"; - - return { - q, - page: parseInt(page), - limit: parseInt(limit), - }; -}; - -export const formatUrlWithNewParams = ( - to: string, - searchParams: ReadonlyURLSearchParams | null, - newParams: Record -) => { - const newSearchParams = new URLSearchParams(searchParams?.toString()); - - Object.entries(newParams).forEach(([key, value]) => { - newSearchParams.set(key, value.toString()); - }); - - newSearchParams.toString(); - - return `${to}?${newSearchParams.toString()}`; -}; diff --git a/yarn.lock b/yarn.lock index c752ba1..422d064 100644 --- a/yarn.lock +++ b/yarn.lock @@ -76,7 +76,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.23.4 resolution: "@babel/runtime@npm:7.23.4" dependencies: @@ -417,23 +417,6 @@ __metadata: languageName: node linkType: hard -"@emotion/server@npm:^11.11.0": - version: 11.11.0 - resolution: "@emotion/server@npm:11.11.0" - dependencies: - "@emotion/utils": ^1.2.1 - html-tokenize: ^2.0.0 - multipipe: ^1.0.2 - through: ^2.3.8 - peerDependencies: - "@emotion/css": ^11.0.0-rc.0 - peerDependenciesMeta: - "@emotion/css": - optional: true - checksum: 2130b51390a6ba4375ec3223c9e4fb476ba30973910ec5196a048d1f832ba2ad23e51eee261058fbd7c3c78938fc3d83b01c3a951e8b6fa83d40f2ac4047c317 - languageName: node - linkType: hard - "@emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -859,16 +842,6 @@ __metadata: languageName: node linkType: hard -"@fastify/auth@npm:^4.4.0": - version: 4.4.0 - resolution: "@fastify/auth@npm:4.4.0" - dependencies: - fastify-plugin: ^4.0.0 - reusify: ^1.0.4 - checksum: 151ff8f4772ef3a9ef969754e65bf3cd891ee1aca20861baf4e16c5aaf989e2495453ffcc195c57edc9d90adfedee067599d8c0d055db903d1ab95d331ada9dc - languageName: node - linkType: hard - "@fastify/busboy@npm:^1.0.0": version: 1.2.1 resolution: "@fastify/busboy@npm:1.2.1" @@ -964,7 +937,7 @@ __metadata: languageName: node linkType: hard -"@fastify/swagger-ui@npm:^1.10.1, @fastify/swagger-ui@npm:^1.8.0": +"@fastify/swagger-ui@npm:^1.8.0": version: 1.10.1 resolution: "@fastify/swagger-ui@npm:1.10.1" dependencies: @@ -977,7 +950,7 @@ __metadata: languageName: node linkType: hard -"@fastify/swagger@npm:^8.12.0, @fastify/swagger@npm:^8.3.1": +"@fastify/swagger@npm:^8.3.1": version: 8.12.0 resolution: "@fastify/swagger@npm:8.12.0" dependencies: @@ -1202,15 +1175,6 @@ __metadata: languageName: node linkType: hard -"@mongodb-js/saslprep@npm:^1.1.0": - version: 1.1.1 - resolution: "@mongodb-js/saslprep@npm:1.1.1" - dependencies: - sparse-bitfield: ^3.0.3 - checksum: 0b263aef5e42a2b296c205a4afcc06c3e59817427dfdf4b5d6f49c4e5c000aa90f652006b95f726e0eac7e888031a82393a964e390d5689a2de61e945f8238d3 - languageName: node - linkType: hard - "@mui/base@npm:5.0.0-beta.24": version: 5.0.0-beta.24 resolution: "@mui/base@npm:5.0.0-beta.24" @@ -1351,7 +1315,7 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.14.16, @mui/utils@npm:^5.14.18": +"@mui/utils@npm:^5.14.18": version: 5.14.18 resolution: "@mui/utils@npm:5.14.18" dependencies: @@ -1369,24 +1333,6 @@ __metadata: languageName: node linkType: hard -"@mui/x-data-grid@npm:^6.13.0": - version: 6.18.1 - resolution: "@mui/x-data-grid@npm:6.18.1" - dependencies: - "@babel/runtime": ^7.23.2 - "@mui/utils": ^5.14.16 - clsx: ^2.0.0 - prop-types: ^15.8.1 - reselect: ^4.1.8 - peerDependencies: - "@mui/material": ^5.4.1 - "@mui/system": ^5.4.1 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - checksum: 606b4ead13a97d1811d73f76a059bdff60a2d92f0d03afac9d9873502d6793a31594df6ee060da184f69a2442007a6a3f968da9432dd95be1560ab3dcec9704a - languageName: node - linkType: hard - "@next/env@npm:13.5.6": version: 13.5.6 resolution: "@next/env@npm:13.5.6" @@ -1835,13 +1781,6 @@ __metadata: languageName: node linkType: hard -"@one-ini/wasm@npm:0.1.1": - version: 0.1.1 - resolution: "@one-ini/wasm@npm:0.1.1" - checksum: 11de17108eae57c797e552e36b259398aede999b4a689d78be6459652edc37f3428472410590a9d328011a8751b771063a5648dd5c4205631c55d1d58e313156 - languageName: node - linkType: hard - "@pdf-lib/standard-fonts@npm:^1.0.0": version: 1.0.0 resolution: "@pdf-lib/standard-fonts@npm:1.0.0" @@ -2254,7 +2193,7 @@ __metadata: languageName: node linkType: hard -"@sentry/node@npm:7.81.1, @sentry/node@npm:^7.60.0, @sentry/node@npm:^7.77.0, @sentry/node@npm:^7.80.0": +"@sentry/node@npm:7.81.1, @sentry/node@npm:^7.60.0, @sentry/node@npm:^7.77.0": version: 7.81.1 resolution: "@sentry/node@npm:7.81.1" dependencies: @@ -2293,7 +2232,7 @@ __metadata: languageName: node linkType: hard -"@sentry/tracing@npm:^7.60.0, @sentry/tracing@npm:^7.77.0": +"@sentry/tracing@npm:^7.60.0": version: 7.81.1 resolution: "@sentry/tracing@npm:7.81.1" dependencies: @@ -2384,13 +2323,6 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/is@npm:^4.0.0": - version: 4.6.0 - resolution: "@sindresorhus/is@npm:4.6.0" - checksum: 83839f13da2c29d55c97abc3bc2c55b250d33a0447554997a85c539e058e57b8da092da396e252b11ec24a0279a0bed1f537fa26302209327060643e327f81d2 - languageName: node - linkType: hard - "@sindresorhus/merge-streams@npm:^1.0.0": version: 1.0.0 resolution: "@sindresorhus/merge-streams@npm:1.0.0" @@ -2407,15 +2339,6 @@ __metadata: languageName: node linkType: hard -"@szmarczak/http-timer@npm:^4.0.5": - version: 4.0.6 - resolution: "@szmarczak/http-timer@npm:4.0.6" - dependencies: - defer-to-connect: ^2.0.0 - checksum: c29df3bcec6fc3bdec2b17981d89d9c9fc9bd7d0c9bcfe92821dc533f4440bc890ccde79971838b4ceed1921d456973c4180d7175ee1d0023ad0562240a58d95 - languageName: node - linkType: hard - "@tanstack/query-core@npm:4.36.1": version: 4.36.1 resolution: "@tanstack/query-core@npm:4.36.1" @@ -2521,18 +2444,6 @@ __metadata: languageName: node linkType: hard -"@types/cacheable-request@npm:^6.0.1": - version: 6.0.3 - resolution: "@types/cacheable-request@npm:6.0.3" - dependencies: - "@types/http-cache-semantics": "*" - "@types/keyv": ^3.1.4 - "@types/node": "*" - "@types/responselike": ^1.0.0 - checksum: d9b26403fe65ce6b0cb3720b7030104c352bcb37e4fac2a7089a25a97de59c355fa08940658751f2f347a8512aa9d18fdb66ab3ade835975b2f454f2d5befbd9 - languageName: node - linkType: hard - "@types/chai-subset@npm:^1.3.3": version: 1.3.5 resolution: "@types/chai-subset@npm:1.3.5" @@ -2558,13 +2469,6 @@ __metadata: languageName: node linkType: hard -"@types/ejs@npm:^3.1.2": - version: 3.1.5 - resolution: "@types/ejs@npm:3.1.5" - checksum: e142266283051f27a7f79329871b311687dede19ae20268d882e4de218c65e1311d28a300b85579ca67157a8d601b7234daa50c2f99b252b121d27b4e5b21468 - languageName: node - linkType: hard - "@types/estree-jsx@npm:^1.0.0": version: 1.0.5 resolution: "@types/estree-jsx@npm:1.0.5" @@ -2590,20 +2494,6 @@ __metadata: languageName: node linkType: hard -"@types/html-to-text@npm:*": - version: 9.0.4 - resolution: "@types/html-to-text@npm:9.0.4" - checksum: 58ab5564080febdf7a5db99e713bdcf1be8b1ca31c40dae76f8278eba6b1cf62a0291082abe1e00537350aaf1c5d64f92ff37b718c1f880bf5e6174fceb41b78 - languageName: node - linkType: hard - -"@types/http-cache-semantics@npm:*": - version: 4.0.4 - resolution: "@types/http-cache-semantics@npm:4.0.4" - checksum: 7f4dd832e618bc1e271be49717d7b4066d77c2d4eed5b81198eb987e532bb3e1c7e02f45d77918185bad936f884b700c10cebe06305f50400f382ab75055f9e8 - languageName: node - linkType: hard - "@types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" @@ -2632,24 +2522,6 @@ __metadata: languageName: node linkType: hard -"@types/jsonwebtoken@npm:^9.0.2": - version: 9.0.5 - resolution: "@types/jsonwebtoken@npm:9.0.5" - dependencies: - "@types/node": "*" - checksum: 07ab6fee602e5bd3fb5c6dfe4ec400769dc20f1d7fce901feecb4c3af5f5f08323b03ea55de3e49b1aa41e171a59008f6f4318738a735588c5268a63eba25337 - languageName: node - linkType: hard - -"@types/keyv@npm:^3.1.4": - version: 3.1.4 - resolution: "@types/keyv@npm:3.1.4" - dependencies: - "@types/node": "*" - checksum: e009a2bfb50e90ca9b7c6e8f648f8464067271fd99116f881073fa6fa76dc8d0133181dd65e6614d5fb1220d671d67b0124aef7d97dc02d7e342ab143a47779d - languageName: node - linkType: hard - "@types/lodash-es@npm:^4.17.8": version: 4.17.11 resolution: "@types/lodash-es@npm:4.17.11" @@ -2684,16 +2556,6 @@ __metadata: languageName: node linkType: hard -"@types/migrate-mongo@npm:^10.0.0": - version: 10.0.4 - resolution: "@types/migrate-mongo@npm:10.0.4" - dependencies: - "@types/node": "*" - mongodb: ^6.1.0 - checksum: 97c6f2664c0f0a73081d5891fb71893d0722f2c459abfa8564a24ac77c9e7667307e557740235be8d06c7e753b552c5585764c8774edb2fe20814b8292b11754 - languageName: node - linkType: hard - "@types/minimist@npm:^1.2.0": version: 1.2.5 resolution: "@types/minimist@npm:1.2.5" @@ -2701,22 +2563,6 @@ __metadata: languageName: node linkType: hard -"@types/mjml-core@npm:*": - version: 4.7.4 - resolution: "@types/mjml-core@npm:4.7.4" - checksum: 174bc57da9b9e3004bd6538cf4c164597469c26f64a87a089feae630b19dad56d0ed9b220587b48092618b1b93d1ac9b521a3a766491a7b8cc15a5e4be512127 - languageName: node - linkType: hard - -"@types/mjml@npm:^4.7.1": - version: 4.7.4 - resolution: "@types/mjml@npm:4.7.4" - dependencies: - "@types/mjml-core": "*" - checksum: 097b46f6d79c02c6d17681d5722bd476f7df7418666673d187824c30994847cd2909bdb0351a878b0690ff5e7bf096a9216e12910c82cba9b88a4ce1b45d803b - languageName: node - linkType: hard - "@types/ms@npm:*": version: 0.7.34 resolution: "@types/ms@npm:0.7.34" @@ -2747,25 +2593,6 @@ __metadata: languageName: node linkType: hard -"@types/nodemailer-html-to-text@npm:^3.1.0": - version: 3.1.3 - resolution: "@types/nodemailer-html-to-text@npm:3.1.3" - dependencies: - "@types/html-to-text": "*" - "@types/nodemailer": "*" - checksum: 2cae371089d0dea31a74a9be25c292fde1514c70c2347bf46cf7c7a14cdba7b560de992b81a2253076b0e0886a83ef29d6c811917fe4e3937cf6b12bfe43c439 - languageName: node - linkType: hard - -"@types/nodemailer@npm:*, @types/nodemailer@npm:^6.4.9": - version: 6.4.14 - resolution: "@types/nodemailer@npm:6.4.14" - dependencies: - "@types/node": "*" - checksum: 5f61f01dd736b17f431d1e8b320322f86460604b45df947fc4bc8999d7c7719405e349f7abba86e4fb100a464a30b52615d00dac03d9cb37562ff04487ebd310 - languageName: node - linkType: hard - "@types/normalize-package-data@npm:^2.4.0, @types/normalize-package-data@npm:^2.4.1": version: 2.4.4 resolution: "@types/normalize-package-data@npm:2.4.4" @@ -2816,15 +2643,6 @@ __metadata: languageName: node linkType: hard -"@types/responselike@npm:^1.0.0": - version: 1.0.3 - resolution: "@types/responselike@npm:1.0.3" - dependencies: - "@types/node": "*" - checksum: 6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 - languageName: node - linkType: hard - "@types/scheduler@npm:*": version: 0.16.7 resolution: "@types/scheduler@npm:0.16.7" @@ -2853,22 +2671,6 @@ __metadata: languageName: node linkType: hard -"@types/webidl-conversions@npm:*": - version: 7.0.3 - resolution: "@types/webidl-conversions@npm:7.0.3" - checksum: 535ead9de4d3d6c8e4f4fa14e9db780d2a31e8020debc062f337e1420a41c3265e223e4f4b628f97a11ecf3b96390962cd88a9ffe34f44e159dec583ff49aa34 - languageName: node - linkType: hard - -"@types/whatwg-url@npm:^11.0.2": - version: 11.0.3 - resolution: "@types/whatwg-url@npm:11.0.3" - dependencies: - "@types/webidl-conversions": "*" - checksum: 400ae723edb3132e7e8fd49a526d108832c1b5a09245511d5175d56a5dc9ae567dd7bbd058bcc799364fed84fbff324736493557913fe9ef3fffb1ad4cff3044 - languageName: node - linkType: hard - "@typescript-eslint/eslint-plugin@npm:^5.62.0": version: 5.62.0 resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" @@ -3319,13 +3121,6 @@ __metadata: languageName: node linkType: hard -"ansi-colors@npm:^4.1.1": - version: 4.1.3 - resolution: "ansi-colors@npm:4.1.3" - checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e - languageName: node - linkType: hard - "ansi-escapes@npm:^5.0.0": version: 5.0.0 resolution: "ansi-escapes@npm:5.0.0" @@ -3617,13 +3412,6 @@ __metadata: languageName: node linkType: hard -"async@npm:^3.2.3": - version: 3.2.5 - resolution: "async@npm:3.2.5" - checksum: 5ec77f1312301dee02d62140a6b1f7ee0edd2a0f983b6fd2b0849b969f245225b990b47b8243e7b9ad16451a53e7f68e753700385b706198ced888beedba3af4 - languageName: node - linkType: hard - "asynciterator.prototype@npm:^1.0.0": version: 1.0.0 resolution: "asynciterator.prototype@npm:1.0.0" @@ -3699,16 +3487,6 @@ __metadata: languageName: node linkType: hard -"axios-retry@npm:^3.8.0": - version: 3.9.1 - resolution: "axios-retry@npm:3.9.1" - dependencies: - "@babel/runtime": ^7.15.4 - is-retry-allowed: ^2.2.0 - checksum: 44e574ad559e4ee638e735662e9b9fcb69a1da6652adc3a75ca4b060e0fd40bdd7ac718e7743f51c0dad54149a6f3c09109275bf90298042542e80a17740a4e5 - languageName: node - linkType: hard - "axios@npm:^1.5.1": version: 1.6.7 resolution: "axios@npm:1.6.7" @@ -3810,13 +3588,6 @@ __metadata: languageName: node linkType: hard -"boolbase@npm:^1.0.0": - version: 1.0.0 - resolution: "boolbase@npm:1.0.0" - checksum: 3e25c80ef626c3a3487c73dbfc70ac322ec830666c9ad915d11b701142fab25ec1e63eff2c450c74347acfd2de854ccde865cd79ef4db1683f7c7b046ea43bb0 - languageName: node - linkType: hard - "bottleneck@npm:^2.15.3": version: 2.19.5 resolution: "bottleneck@npm:2.19.5" @@ -3852,34 +3623,6 @@ __metadata: languageName: node linkType: hard -"bson@npm:^5.4.0": - version: 5.5.1 - resolution: "bson@npm:5.5.1" - checksum: f49730504e8362e2c8d1eb0c272e5e125392c41fb7196fc35ccbc39718ee62569a1d197bd2342c3334cd420073d3fd5dc7dea764a7f219dcd79e0ce473dd2772 - languageName: node - linkType: hard - -"bson@npm:^6.2.0": - version: 6.2.0 - resolution: "bson@npm:6.2.0" - checksum: 950fccd2abd0ff5a1bd3637f4697631298f1538314994ab8c9e13f1c9851d0fd042b54fe8340e00151c2acee43917ea40e64b800ceeea811b00f2de3e900c77e - languageName: node - linkType: hard - -"buffer-equal-constant-time@npm:1.0.1": - version: 1.0.1 - resolution: "buffer-equal-constant-time@npm:1.0.1" - checksum: 80bb945f5d782a56f374b292770901065bad21420e34936ecbe949e57724b4a13874f735850dd1cc61f078773c4fb5493a41391e7bda40d1fa388d6bd80daaab - languageName: node - linkType: hard - -"buffer-from@npm:~0.1.1": - version: 0.1.2 - resolution: "buffer-from@npm:0.1.2" - checksum: 50a1fa5da97d2081b7d945483c8967d3b89a096fa585eb55000bb2100e827c647c9370280ec9bd057da8f9fa5abc1d3b764228851a31fa8a67f659f70c0052d8 - languageName: node - linkType: hard - "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -4036,28 +3779,6 @@ __metadata: languageName: node linkType: hard -"cacheable-lookup@npm:^5.0.3": - version: 5.0.4 - resolution: "cacheable-lookup@npm:5.0.4" - checksum: 763e02cf9196bc9afccacd8c418d942fc2677f22261969a4c2c2e760fa44a2351a81557bd908291c3921fe9beb10b976ba8fa50c5ca837c5a0dd945f16468f2d - languageName: node - linkType: hard - -"cacheable-request@npm:^7.0.2": - version: 7.0.4 - resolution: "cacheable-request@npm:7.0.4" - dependencies: - clone-response: ^1.0.2 - get-stream: ^5.1.0 - http-cache-semantics: ^4.0.0 - keyv: ^4.0.0 - lowercase-keys: ^2.0.0 - normalize-url: ^6.0.1 - responselike: ^2.0.0 - checksum: 0de9df773fd4e7dd9bd118959878f8f2163867e2e1ab3575ffbecbe6e75e80513dd0c68ba30005e5e5a7b377cc6162bbc00ab1db019bb4e9cb3c2f3f7a6f1ee4 - languageName: node - linkType: hard - "call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": version: 1.0.5 resolution: "call-bind@npm:1.0.5" @@ -4076,16 +3797,6 @@ __metadata: languageName: node linkType: hard -"camel-case@npm:^3.0.0": - version: 3.0.0 - resolution: "camel-case@npm:3.0.0" - dependencies: - no-case: ^2.2.0 - upper-case: ^1.1.1 - checksum: 4190ed6ab8acf4f3f6e1a78ad4d0f3f15ce717b6bfa1b5686d58e4bcd29960f6e312dd746b5fa259c6d452f1413caef25aee2e10c9b9a580ac83e516533a961a - languageName: node - linkType: hard - "camelcase-keys@npm:^6.2.2": version: 6.2.2 resolution: "camelcase-keys@npm:6.2.2" @@ -4187,7 +3898,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0": +"chalk@npm:^4.0.0, chalk@npm:^4.1.0": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -4255,36 +3966,7 @@ __metadata: languageName: node linkType: hard -"cheerio-select@npm:^2.1.0": - version: 2.1.0 - resolution: "cheerio-select@npm:2.1.0" - dependencies: - boolbase: ^1.0.0 - css-select: ^5.1.0 - css-what: ^6.1.0 - domelementtype: ^2.3.0 - domhandler: ^5.0.3 - domutils: ^3.0.1 - checksum: 843d6d479922f28a6c5342c935aff1347491156814de63c585a6eb73baf7bb4185c1b4383a1195dca0f12e3946d737c7763bcef0b9544c515d905c5c44c5308b - languageName: node - linkType: hard - -"cheerio@npm:1.0.0-rc.12, cheerio@npm:^1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "cheerio@npm:1.0.0-rc.12" - dependencies: - cheerio-select: ^2.1.0 - dom-serializer: ^2.0.0 - domhandler: ^5.0.3 - domutils: ^3.0.1 - htmlparser2: ^8.0.1 - parse5: ^7.0.0 - parse5-htmlparser2-tree-adapter: ^7.0.0 - checksum: 5d4c1b7a53cf22d3a2eddc0aff70cf23cbb30d01a4c79013e703a012475c02461aa1fcd99127e8d83a02216386ed6942b2c8103845fd0812300dd199e6e7e054 - languageName: node - linkType: hard - -"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.0.0, chokidar@npm:^3.5.1": +"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.5.1": version: 3.5.3 resolution: "chokidar@npm:3.5.3" dependencies: @@ -4333,15 +4015,6 @@ __metadata: languageName: node linkType: hard -"clean-css@npm:^4.2.1": - version: 4.2.4 - resolution: "clean-css@npm:4.2.4" - dependencies: - source-map: ~0.6.0 - checksum: 045ff6fcf4b5c76a084b24e1633e0c78a13b24080338fc8544565a9751559aa32ff4ee5886d9e52c18a644a6ff119bd8e37bc58e574377c05382a1fb7dbe39f8 - languageName: node - linkType: hard - "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -4386,7 +4059,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.1, cli-table3@npm:^0.6.3": +"cli-table3@npm:^0.6.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -4416,17 +4089,6 @@ __metadata: languageName: node linkType: hard -"cliui@npm:^7.0.2": - version: 7.0.4 - resolution: "cliui@npm:7.0.4" - dependencies: - string-width: ^4.2.0 - strip-ansi: ^6.0.0 - wrap-ansi: ^7.0.0 - checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f - languageName: node - linkType: hard - "cliui@npm:^8.0.1": version: 8.0.1 resolution: "cliui@npm:8.0.1" @@ -4445,15 +4107,6 @@ __metadata: languageName: node linkType: hard -"clone-response@npm:^1.0.2": - version: 1.0.3 - resolution: "clone-response@npm:1.0.3" - dependencies: - mimic-response: ^1.0.0 - checksum: 4e671cac39b11c60aa8ba0a450657194a5d6504df51bca3fac5b3bd0145c4f8e8464898f87c8406b83232e3bc5cca555f51c1f9c8ac023969ebfbf7f6bdabb2e - languageName: node - linkType: hard - "clone@npm:^1.0.2": version: 1.0.4 resolution: "clone@npm:1.0.4" @@ -4516,7 +4169,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.20, colorette@npm:^2.0.7": +"colorette@npm:^2.0.20": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d @@ -4556,20 +4209,13 @@ __metadata: languageName: node linkType: hard -"commander@npm:^10.0.0, commander@npm:^10.0.1": +"commander@npm:^10.0.1": version: 10.0.1 resolution: "commander@npm:10.0.1" checksum: 436901d64a818295803c1996cd856621a74f30b9f9e28a588e726b2b1670665bccd7c1a77007ebf328729f0139838a88a19265858a0fa7a8728c4656796db948 languageName: node linkType: hard -"commander@npm:^2.19.0": - version: 2.20.3 - resolution: "commander@npm:2.20.3" - checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e - languageName: node - linkType: hard - "commander@npm:^4.0.0": version: 4.1.1 resolution: "commander@npm:4.1.1" @@ -4577,13 +4223,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^6.1.0": - version: 6.2.1 - resolution: "commander@npm:6.2.1" - checksum: d7090410c0de6bc5c67d3ca41c41760d6d268f3c799e530aafb73b7437d1826bbf0d2a3edac33f8b57cc9887b4a986dce307fa5557e109be40eadb7c43b21742 - languageName: node - linkType: hard - "commander@npm:^8.0.0": version: 8.3.0 resolution: "commander@npm:8.3.0" @@ -4591,13 +4230,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^9.1.0": - version: 9.5.0 - resolution: "commander@npm:9.5.0" - checksum: c7a3e27aa59e913b54a1bafd366b88650bc41d6651f0cbe258d4ff09d43d6a7394232a4dadd0bf518b3e696fdf595db1028a0d82c785b88bd61f8a440cecfade - languageName: node - linkType: hard - "common-ancestor-path@npm:^1.0.1": version: 1.0.1 resolution: "common-ancestor-path@npm:1.0.1" @@ -4629,7 +4261,7 @@ __metadata: languageName: node linkType: hard -"config-chain@npm:^1.1.11, config-chain@npm:^1.1.13": +"config-chain@npm:^1.1.11": version: 1.1.13 resolution: "config-chain@npm:1.1.13" dependencies: @@ -4842,15 +4474,6 @@ __metadata: languageName: node linkType: hard -"cron-parser@npm:^4.9.0": - version: 4.9.0 - resolution: "cron-parser@npm:4.9.0" - dependencies: - luxon: ^3.2.1 - checksum: 3cf248fc5cae6c19ec7124962b1cd84b76f02b9bc4f58976b3bd07624db3ef10aaf1548efcc2d2dcdab0dad4f12029d640a55ecce05ea5e1596af9db585502cf - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -4880,19 +4503,6 @@ __metadata: languageName: node linkType: hard -"css-select@npm:^5.1.0": - version: 5.1.0 - resolution: "css-select@npm:5.1.0" - dependencies: - boolbase: ^1.0.0 - css-what: ^6.1.0 - domhandler: ^5.0.2 - domutils: ^3.0.1 - nth-check: ^2.0.1 - checksum: 2772c049b188d3b8a8159907192e926e11824aea525b8282981f72ba3f349cf9ecd523fdf7734875ee2cb772246c22117fc062da105b6d59afe8dcd5c99c9bda - languageName: node - linkType: hard - "css-tree@npm:^1.1.2": version: 1.1.3 resolution: "css-tree@npm:1.1.3" @@ -4903,13 +4513,6 @@ __metadata: languageName: node linkType: hard -"css-what@npm:^6.1.0": - version: 6.1.0 - resolution: "css-what@npm:6.1.0" - checksum: b975e547e1e90b79625918f84e67db5d33d896e6de846c9b584094e529f0c63e2ab85ee33b9daffd05bff3a146a1916bec664e18bb76dd5f66cbff9fc13b2bbe - languageName: node - linkType: hard - "cssesc@npm:^3.0.0": version: 3.0.0 resolution: "cssesc@npm:3.0.0" @@ -4926,13 +4529,6 @@ __metadata: languageName: node linkType: hard -"csv-parse@npm:^5.4.0": - version: 5.5.2 - resolution: "csv-parse@npm:5.5.2" - checksum: de2eb0c29b049783ef101b7eb843456200dc9a4fc9f4b400473bb0521b41aadb77af560cf4edc49bac65cc457b32596519860120181b26ec3b372109ddf8e8ea - languageName: node - linkType: hard - "damerau-levenshtein@npm:^1.0.8": version: 1.0.8 resolution: "damerau-levenshtein@npm:1.0.8" @@ -4956,7 +4552,7 @@ __metadata: languageName: node linkType: hard -"date-fns@npm:^2.28.0, date-fns@npm:^2.30.0": +"date-fns@npm:^2.30.0": version: 2.30.0 resolution: "date-fns@npm:2.30.0" dependencies: @@ -4972,14 +4568,7 @@ __metadata: languageName: node linkType: hard -"dateformat@npm:^4.6.3": - version: 4.6.3 - resolution: "dateformat@npm:4.6.3" - checksum: c3aa0617c0a5b30595122bc8d1bee6276a9221e4d392087b41cbbdf175d9662ae0e50d0d6dcdf45caeac5153c4b5b0844265f8cd2b2245451e3da19e39e3b65d - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -5033,15 +4622,6 @@ __metadata: languageName: node linkType: hard -"decompress-response@npm:^6.0.0": - version: 6.0.0 - resolution: "decompress-response@npm:6.0.0" - dependencies: - mimic-response: ^3.1.0 - checksum: d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 - languageName: node - linkType: hard - "deep-eql@npm:^4.1.3": version: 4.1.3 resolution: "deep-eql@npm:4.1.3" @@ -5065,13 +4645,6 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.2.2": - version: 4.3.1 - resolution: "deepmerge@npm:4.3.1" - checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052 - languageName: node - linkType: hard - "defaults@npm:^1.0.3": version: 1.0.4 resolution: "defaults@npm:1.0.4" @@ -5081,13 +4654,6 @@ __metadata: languageName: node linkType: hard -"defer-to-connect@npm:^2.0.0": - version: 2.0.1 - resolution: "defer-to-connect@npm:2.0.1" - checksum: 8a9b50d2f25446c0bfefb55a48e90afd58f85b21bcf78e9207cd7b804354f6409032a1705c2491686e202e64fc05f147aa5aa45f9aa82627563f045937f5791b - languageName: node - linkType: hard - "define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": version: 1.1.1 resolution: "define-data-property@npm:1.1.1" @@ -5145,20 +4711,6 @@ __metadata: languageName: node linkType: hard -"detect-node@npm:2.0.4": - version: 2.0.4 - resolution: "detect-node@npm:2.0.4" - checksum: c06ae40fefbad8cb8cbb6ca819c93568b2a809e747bfc9c71f3524b027f5e988163b0ac0517fd65288b375360b30bc4822172eb05d211f99003d73cf8ec22911 - languageName: node - linkType: hard - -"detect-node@npm:^2.0.4": - version: 2.1.0 - resolution: "detect-node@npm:2.1.0" - checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e - languageName: node - linkType: hard - "devlop@npm:^1.0.0, devlop@npm:^1.1.0": version: 1.1.0 resolution: "devlop@npm:1.1.0" @@ -5226,123 +4778,38 @@ __metadata: languageName: node linkType: hard -"dom-serializer@npm:^1.0.1": - version: 1.4.1 - resolution: "dom-serializer@npm:1.4.1" - dependencies: - domelementtype: ^2.0.1 - domhandler: ^4.2.0 - entities: ^2.0.0 - checksum: fbb0b01f87a8a2d18e6e5a388ad0f7ec4a5c05c06d219377da1abc7bb0f674d804f4a8a94e3f71ff15f6cb7dcfc75704a54b261db672b9b3ab03da6b758b0b22 - languageName: node - linkType: hard - -"dom-serializer@npm:^2.0.0": - version: 2.0.0 - resolution: "dom-serializer@npm:2.0.0" +"dot-prop@npm:^5.1.0": + version: 5.3.0 + resolution: "dot-prop@npm:5.3.0" dependencies: - domelementtype: ^2.3.0 - domhandler: ^5.0.2 - entities: ^4.2.0 - checksum: cd1810544fd8cdfbd51fa2c0c1128ec3a13ba92f14e61b7650b5de421b88205fd2e3f0cc6ace82f13334114addb90ed1c2f23074a51770a8e9c1273acbc7f3e6 + is-obj: ^2.0.0 + checksum: d5775790093c234ef4bfd5fbe40884ff7e6c87573e5339432870616331189f7f5d86575c5b5af2dcf0f61172990f4f734d07844b1f23482fff09e3c4bead05ea languageName: node linkType: hard -"dom-walk@npm:^0.1.0": - version: 0.1.2 - resolution: "dom-walk@npm:0.1.2" - checksum: 19eb0ce9c6de39d5e231530685248545d9cd2bd97b2cb3486e0bfc0f2a393a9addddfd5557463a932b52fdfcf68ad2a619020cd2c74a5fe46fbecaa8e80872f3 +"dotenv@npm:^16.4.5": + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 301a12c3d44fd49888b74eb9ccf9f07a1f5df43f489e7fcb89647a2edcd84c42d6bc349dc8df099cd18f07c35c7b04685c1a4f3e6a6a9e6b30f8d48c15b7f49c languageName: node linkType: hard -"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": - version: 2.3.0 - resolution: "domelementtype@npm:2.3.0" - checksum: ee837a318ff702622f383409d1f5b25dd1024b692ef64d3096ff702e26339f8e345820f29a68bcdcea8cfee3531776b3382651232fbeae95612d6f0a75efb4f6 +"dtrace-provider@npm:~0.8": + version: 0.8.8 + resolution: "dtrace-provider@npm:0.8.8" + dependencies: + nan: ^2.14.0 + node-gyp: latest + checksum: f2dc89df6a9c443dc9bae3b53496e0685b5da89142951d451c1ce062c75d96698ffc0b3d90f621a59a6a18578be552378ad4e08210759038910ff2080be556b9 languageName: node linkType: hard -"domhandler@npm:^3.3.0": - version: 3.3.0 - resolution: "domhandler@npm:3.3.0" +"duplexer2@npm:~0.1.0": + version: 0.1.4 + resolution: "duplexer2@npm:0.1.4" dependencies: - domelementtype: ^2.0.1 - checksum: 850e5e9fee7834ab4314811e18bc1f4294d7eafbf6a79ad03cbe50cf964108935c97257ac248944d72a9312b4a18dfa8323e857d23278964dc83b1f124467fa3 - languageName: node - linkType: hard - -"domhandler@npm:^4.0.0, domhandler@npm:^4.2.0": - version: 4.3.1 - resolution: "domhandler@npm:4.3.1" - dependencies: - domelementtype: ^2.2.0 - checksum: 4c665ceed016e1911bf7d1dadc09dc888090b64dee7851cccd2fcf5442747ec39c647bb1cb8c8919f8bbdd0f0c625a6bafeeed4b2d656bbecdbae893f43ffaaa - languageName: node - linkType: hard - -"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": - version: 5.0.3 - resolution: "domhandler@npm:5.0.3" - dependencies: - domelementtype: ^2.3.0 - checksum: 0f58f4a6af63e6f3a4320aa446d28b5790a009018707bce2859dcb1d21144c7876482b5188395a188dfa974238c019e0a1e610d2fc269a12b2c192ea2b0b131c - languageName: node - linkType: hard - -"domutils@npm:^2.4.2, domutils@npm:^2.5.2": - version: 2.8.0 - resolution: "domutils@npm:2.8.0" - dependencies: - dom-serializer: ^1.0.1 - domelementtype: ^2.2.0 - domhandler: ^4.2.0 - checksum: abf7434315283e9aadc2a24bac0e00eab07ae4313b40cc239f89d84d7315ebdfd2fb1b5bf750a96bc1b4403d7237c7b2ebf60459be394d625ead4ca89b934391 - languageName: node - linkType: hard - -"domutils@npm:^3.0.1": - version: 3.1.0 - resolution: "domutils@npm:3.1.0" - dependencies: - dom-serializer: ^2.0.0 - domelementtype: ^2.3.0 - domhandler: ^5.0.3 - checksum: e5757456ddd173caa411cfc02c2bb64133c65546d2c4081381a3bafc8a57411a41eed70494551aa58030be9e58574fcc489828bebd673863d39924fb4878f416 - languageName: node - linkType: hard - -"dot-prop@npm:^5.1.0": - version: 5.3.0 - resolution: "dot-prop@npm:5.3.0" - dependencies: - is-obj: ^2.0.0 - checksum: d5775790093c234ef4bfd5fbe40884ff7e6c87573e5339432870616331189f7f5d86575c5b5af2dcf0f61172990f4f734d07844b1f23482fff09e3c4bead05ea - languageName: node - linkType: hard - -"dotenv@npm:^16.4.5": - version: 16.4.5 - resolution: "dotenv@npm:16.4.5" - checksum: 301a12c3d44fd49888b74eb9ccf9f07a1f5df43f489e7fcb89647a2edcd84c42d6bc349dc8df099cd18f07c35c7b04685c1a4f3e6a6a9e6b30f8d48c15b7f49c - languageName: node - linkType: hard - -"dtrace-provider@npm:~0.8": - version: 0.8.8 - resolution: "dtrace-provider@npm:0.8.8" - dependencies: - nan: ^2.14.0 - node-gyp: latest - checksum: f2dc89df6a9c443dc9bae3b53496e0685b5da89142951d451c1ce062c75d96698ffc0b3d90f621a59a6a18578be552378ad4e08210759038910ff2080be556b9 - languageName: node - linkType: hard - -"duplexer2@npm:^0.1.2, duplexer2@npm:~0.1.0": - version: 0.1.4 - resolution: "duplexer2@npm:0.1.4" - dependencies: - readable-stream: ^2.0.2 - checksum: 744961f03c7f54313f90555ac20284a3fb7bf22fdff6538f041a86c22499560eb6eac9d30ab5768054137cb40e6b18b40f621094e0261d7d8c35a37b7a5ad241 + readable-stream: ^2.0.2 + checksum: 744961f03c7f54313f90555ac20284a3fb7bf22fdff6538f041a86c22499560eb6eac9d30ab5768054137cb40e6b18b40f621094e0261d7d8c35a37b7a5ad241 languageName: node linkType: hard @@ -5363,40 +4830,6 @@ __metadata: languageName: node linkType: hard -"ecdsa-sig-formatter@npm:1.0.11": - version: 1.0.11 - resolution: "ecdsa-sig-formatter@npm:1.0.11" - dependencies: - safe-buffer: ^5.0.1 - checksum: 207f9ab1c2669b8e65540bce29506134613dd5f122cccf1e6a560f4d63f2732d427d938f8481df175505aad94583bcb32c688737bb39a6df0625f903d6d93c03 - languageName: node - linkType: hard - -"editorconfig@npm:^1.0.3": - version: 1.0.4 - resolution: "editorconfig@npm:1.0.4" - dependencies: - "@one-ini/wasm": 0.1.1 - commander: ^10.0.0 - minimatch: 9.0.1 - semver: ^7.5.3 - bin: - editorconfig: bin/editorconfig - checksum: 09904f19381b3ddf132cea0762971aba887236f387be3540909e96b8eb9337e1793834e10f06890cd8e8e7bb1ba80cb13e7d50a863f227806c9ca74def4165fb - languageName: node - linkType: hard - -"ejs@npm:^3.1.9": - version: 3.1.9 - resolution: "ejs@npm:3.1.9" - dependencies: - jake: ^10.8.5 - bin: - ejs: bin/cli.js - checksum: af6f10eb815885ff8a8cfacc42c6b6cf87daf97a4884f87a30e0c3271fedd85d76a3a297d9c33a70e735b97ee632887f85e32854b9cdd3a2d97edf931519a35f - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -5427,15 +4860,6 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0": - version: 1.4.4 - resolution: "end-of-stream@npm:1.4.4" - dependencies: - once: ^1.4.0 - checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b - languageName: node - linkType: hard - "enhanced-resolve@npm:^5.12.0": version: 5.15.0 resolution: "enhanced-resolve@npm:5.15.0" @@ -5446,20 +4870,6 @@ __metadata: languageName: node linkType: hard -"entities@npm:^2.0.0": - version: 2.2.0 - resolution: "entities@npm:2.2.0" - checksum: 19010dacaf0912c895ea262b4f6128574f9ccf8d4b3b65c7e8334ad0079b3706376360e28d8843ff50a78aabcb8f08f0a32dbfacdc77e47ed77ca08b713669b3 - languageName: node - linkType: hard - -"entities@npm:^4.2.0, entities@npm:^4.4.0": - version: 4.5.0 - resolution: "entities@npm:4.5.0" - checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 - languageName: node - linkType: hard - "env-ci@npm:^9.0.0": version: 9.1.1 resolution: "env-ci@npm:9.1.1" @@ -5770,13 +5180,6 @@ __metadata: languageName: node linkType: hard -"escape-goat@npm:^3.0.0": - version: 3.0.0 - resolution: "escape-goat@npm:3.0.0" - checksum: 6719196d073cc72d0bbe079646d6fa32f226f24fd7d00c1a71fa375bd4c5b8999050021d9e62c232a8874230328ebf89a5c8bd76fb72f7ccd6229efbe5abd04e - languageName: node - linkType: hard - "escape-html@npm:~1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" @@ -6373,13 +5776,6 @@ __metadata: languageName: node linkType: hard -"fast-copy@npm:^3.0.0": - version: 3.0.1 - resolution: "fast-copy@npm:3.0.1" - checksum: 5496b5cf47df29eea479deef03b6b7188626a2cbc356b3015649062846729de6f1a9f555f937e772da8feae0a1231fab13096ed32424b2d61e4d065abc9969fe - languageName: node - linkType: hard - "fast-decode-uri-component@npm:^1.0.1": version: 1.0.1 resolution: "fast-decode-uri-component@npm:1.0.1" @@ -6466,13 +5862,6 @@ __metadata: languageName: node linkType: hard -"fast-safe-stringify@npm:^2.1.1": - version: 2.1.1 - resolution: "fast-safe-stringify@npm:2.1.1" - checksum: a851cbddc451745662f8f00ddb622d6766f9bd97642dabfd9a405fb0d646d69fc0b9a1243cbf67f5f18a39f40f6fa821737651ff1bceeba06c9992ca2dc5bd3d - languageName: node - linkType: hard - "fast-shallow-equal@npm:^1.0.0": version: 1.0.0 resolution: "fast-shallow-equal@npm:1.0.0" @@ -6593,15 +5982,6 @@ __metadata: languageName: node linkType: hard -"filelist@npm:^1.0.4": - version: 1.0.4 - resolution: "filelist@npm:1.0.4" - dependencies: - minimatch: ^5.0.1 - checksum: a303573b0821e17f2d5e9783688ab6fbfce5d52aaac842790ae85e704a6f5e4e3538660a63183d6453834dedf1e0f19a9dadcebfa3e926c72397694ea11f5160 - languageName: node - linkType: hard - "fill-range@npm:^7.0.1": version: 7.0.1 resolution: "fill-range@npm:7.0.1" @@ -6702,13 +6082,6 @@ __metadata: languageName: node linkType: hard -"fn-args@npm:^5.0.0": - version: 5.0.0 - resolution: "fn-args@npm:5.0.0" - checksum: 51af66d5188a6243a33a9afc7309bcf24908331b16d8df2c10afad8dea0f39985e50ab9b53fd4bc4dfebcdc3cf7e1cb80cd46c76d69d34e4fd9deaa170b19765 - languageName: node - linkType: hard - "follow-redirects@npm:^1.15.4": version: 1.15.5 resolution: "follow-redirects@npm:1.15.5" @@ -6784,17 +6157,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^10.0.1": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" - dependencies: - graceful-fs: ^4.2.0 - jsonfile: ^6.0.1 - universalify: ^2.0.0 - checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 - languageName: node - linkType: hard - "fs-extra@npm:^11.0.0": version: 11.1.1 resolution: "fs-extra@npm:11.1.1" @@ -6934,15 +6296,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^5.1.0": - version: 5.2.0 - resolution: "get-stream@npm:5.2.0" - dependencies: - pump: ^3.0.0 - checksum: 8bc1a23174a06b2b4ce600df38d6c98d2ef6d84e020c1ddad632ad75bac4e092eeb40e4c09e0761c35fc2dbc5e7fff5dab5e763a383582c4a167dd69a905bd12 - languageName: node - linkType: hard - "get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -7074,7 +6427,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.2.7, glob@npm:^10.3.10, glob@npm:^10.3.3": +"glob@npm:^10.2.2, glob@npm:^10.2.7, glob@npm:^10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -7102,7 +6455,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4": +"glob@npm:^7.1.3, glob@npm:^7.1.4": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -7116,7 +6469,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^8.0.0, glob@npm:^8.0.1, glob@npm:^8.0.3": +"glob@npm:^8.0.1, glob@npm:^8.0.3": version: 8.1.0 resolution: "glob@npm:8.1.0" dependencies: @@ -7138,16 +6491,6 @@ __metadata: languageName: node linkType: hard -"global@npm:4.4.0": - version: 4.4.0 - resolution: "global@npm:4.4.0" - dependencies: - min-document: ^2.19.0 - process: ^0.11.10 - checksum: 9c057557c8f5a5bcfbeb9378ba4fe2255d04679452be504608dd5f13b54edf79f7be1db1031ea06a4ec6edd3b9f5f17d2d172fb47e6c69dae57fd84b7e72b77f - languageName: node - linkType: hard - "globals@npm:^13.19.0": version: 13.23.0 resolution: "globals@npm:13.23.0" @@ -7210,25 +6553,6 @@ __metadata: languageName: node linkType: hard -"got@npm:^11.8.1": - version: 11.8.6 - resolution: "got@npm:11.8.6" - dependencies: - "@sindresorhus/is": ^4.0.0 - "@szmarczak/http-timer": ^4.0.5 - "@types/cacheable-request": ^6.0.1 - "@types/responselike": ^1.0.0 - cacheable-lookup: ^5.0.3 - cacheable-request: ^7.0.2 - decompress-response: ^6.0.0 - http2-wrapper: ^1.0.0-beta.5.2 - lowercase-keys: ^2.0.0 - p-cancelable: ^2.0.0 - responselike: ^2.0.0 - checksum: bbc783578a8d5030c8164ef7f57ce41b5ad7db2ed13371e1944bef157eeca5a7475530e07c0aaa71610d7085474d0d96222c9f4268d41db333a17e39b463f45d - languageName: node - linkType: hard - "graceful-fs@npm:4.2.10": version: 4.2.10 resolution: "graceful-fs@npm:4.2.10" @@ -7400,25 +6724,6 @@ __metadata: languageName: node linkType: hard -"he@npm:^1.2.0": - version: 1.2.0 - resolution: "he@npm:1.2.0" - bin: - he: bin/he - checksum: 3d4d6babccccd79c5c5a3f929a68af33360d6445587d628087f39a965079d84f18ce9c3d3f917ee1e3978916fc833bb8b29377c3b403f919426f91bc6965e7a7 - languageName: node - linkType: hard - -"help-me@npm:^4.0.1": - version: 4.2.0 - resolution: "help-me@npm:4.2.0" - dependencies: - glob: ^8.0.0 - readable-stream: ^3.6.0 - checksum: 6548acba10dd79ebfc93f0d739c4cb2f32f7932c8d87b091992f3a0f844706263415eab81be015aed4ab874154232beb666920d7e280502c6bba29a40cde343e - languageName: node - linkType: hard - "hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -7483,52 +6788,6 @@ __metadata: languageName: node linkType: hard -"html-minifier@npm:^4.0.0": - version: 4.0.0 - resolution: "html-minifier@npm:4.0.0" - dependencies: - camel-case: ^3.0.0 - clean-css: ^4.2.1 - commander: ^2.19.0 - he: ^1.2.0 - param-case: ^2.1.1 - relateurl: ^0.2.7 - uglify-js: ^3.5.1 - bin: - html-minifier: ./cli.js - checksum: b426aee771d9da104c1c9554e3ebd3a4f483d2ce01f4dcc4156ba33a5959044acf6bea192d5ae63b290cdb92c30a9d07fd6924c65609aa82382ce411328f94ca - languageName: node - linkType: hard - -"html-to-text@npm:7.1.1": - version: 7.1.1 - resolution: "html-to-text@npm:7.1.1" - dependencies: - deepmerge: ^4.2.2 - he: ^1.2.0 - htmlparser2: ^6.1.0 - minimist: ^1.2.5 - bin: - html-to-text: bin/cli.js - checksum: 5b50c08f1b4897efba185c5ecc5eb087eaf69c6d93027c39681272ab0d9a92bdac1894bcb5cf26039e8226217aa0c690d1084393b10d9570202c14b381da1406 - languageName: node - linkType: hard - -"html-tokenize@npm:^2.0.0": - version: 2.0.1 - resolution: "html-tokenize@npm:2.0.1" - dependencies: - buffer-from: ~0.1.1 - inherits: ~2.0.1 - minimist: ~1.2.5 - readable-stream: ~1.0.27-1 - through2: ~0.4.1 - bin: - html-tokenize: bin/cmd.js - checksum: 4e04078fd22cf274fc1fa430490af3feda1c3bc4dd2fc88880caf6c2e816992d508bc44a7b16721b713a6b98d880f43e10ea4b169529056134cd488403adc8fc - languageName: node - linkType: hard - "html-url-attributes@npm:^3.0.0": version: 3.0.0 resolution: "html-url-attributes@npm:3.0.0" @@ -7536,43 +6795,7 @@ __metadata: languageName: node linkType: hard -"htmlparser2@npm:^5.0.0": - version: 5.0.1 - resolution: "htmlparser2@npm:5.0.1" - dependencies: - domelementtype: ^2.0.1 - domhandler: ^3.3.0 - domutils: ^2.4.2 - entities: ^2.0.0 - checksum: b67ac02e44629ec76b712fc06702451bea64e522cfcd7cc22fa85023b81b44cde5060662faa81d34f18c0fe5a43ced1cac73528d30a6df5ac5825a4d479c7ea5 - languageName: node - linkType: hard - -"htmlparser2@npm:^6.1.0": - version: 6.1.0 - resolution: "htmlparser2@npm:6.1.0" - dependencies: - domelementtype: ^2.0.1 - domhandler: ^4.0.0 - domutils: ^2.5.2 - entities: ^2.0.0 - checksum: 81a7b3d9c3bb9acb568a02fc9b1b81ffbfa55eae7f1c41ae0bf840006d1dbf54cb3aa245b2553e2c94db674840a9f0fdad7027c9a9d01a062065314039058c4e - languageName: node - linkType: hard - -"htmlparser2@npm:^8.0.1": - version: 8.0.2 - resolution: "htmlparser2@npm:8.0.2" - dependencies: - domelementtype: ^2.3.0 - domhandler: ^5.0.3 - domutils: ^3.0.1 - entities: ^4.4.0 - checksum: 29167a0f9282f181da8a6d0311b76820c8a59bc9e3c87009e21968264c2987d2723d6fde5a964d4b7b6cba663fca96ffb373c06d8223a85f52a6089ced942700 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0, http-cache-semantics@npm:^4.1.1": +"http-cache-semantics@npm:^4.1.0, http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 @@ -7624,16 +6847,6 @@ __metadata: languageName: node linkType: hard -"http2-wrapper@npm:^1.0.0-beta.5.2": - version: 1.0.3 - resolution: "http2-wrapper@npm:1.0.3" - dependencies: - quick-lru: ^5.1.1 - resolve-alpn: ^1.0.0 - checksum: 74160b862ec699e3f859739101ff592d52ce1cb207b7950295bf7962e4aa1597ef709b4292c673bece9c9b300efad0559fc86c71b1409c7a1e02b7229456003e - languageName: node - linkType: hard - "https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -7810,7 +7023,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:~2.0.1, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 @@ -8227,13 +7440,6 @@ __metadata: languageName: node linkType: hard -"is-retry-allowed@npm:^2.2.0": - version: 2.2.0 - resolution: "is-retry-allowed@npm:2.2.0" - checksum: 3d1103a9290b5d03626756a41054844633eac78bc5d3e3a95b13afeae94fa3cfbcf7f0b5520d83f75f48a25ce7b142fdbac4217dc4b0630f3ea55e866ec3a029 - languageName: node - linkType: hard - "is-set@npm:^2.0.1": version: 2.0.2 resolution: "is-set@npm:2.0.2" @@ -8356,13 +7562,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:0.0.1": - version: 0.0.1 - resolution: "isarray@npm:0.0.1" - checksum: 49191f1425681df4a18c2f0f93db3adb85573bcdd6a4482539d98eac9e705d8961317b01175627e860516a2fc45f8f9302db26e5a380a97a520e272e2a40a8d4 - languageName: node - linkType: hard - "isarray@npm:^2.0.5": version: 2.0.5 resolution: "isarray@npm:2.0.5" @@ -8476,20 +7675,6 @@ __metadata: languageName: node linkType: hard -"jake@npm:^10.8.5": - version: 10.8.7 - resolution: "jake@npm:10.8.7" - dependencies: - async: ^3.2.3 - chalk: ^4.0.2 - filelist: ^1.0.4 - minimatch: ^3.1.2 - bin: - jake: bin/cli.js - checksum: a23fd2273fb13f0d0d845502d02c791fd55ef5c6a2d207df72f72d8e1eac6d2b8ffa6caf660bc8006b3242e0daaa88a3ecc600194d72b5c6016ad56e9cd43553 - languageName: node - linkType: hard - "java-properties@npm:^1.0.2": version: 1.0.2 resolution: "java-properties@npm:1.0.2" @@ -8497,44 +7682,13 @@ __metadata: languageName: node linkType: hard -"job-processor@npm:^1.4.7": - version: 1.4.7 - resolution: "job-processor@npm:1.4.7" - dependencies: - "@sentry/node": ^7.80.0 - cron-parser: ^4.9.0 - date-fns: ^2.30.0 - peerDependencies: - mongodb: "*" - zod: ^3.0.0 - zod-mongodb-schema: ^1.0.0-next.3 - checksum: bd1c35abf24b84f7de8a019164967d01750a1f9067fcf4a50a871d6aee468e5e6844315d3b2526e0a5d085c7cff3c6b1d63e9939a68f2e25d31ced54a2bf3e36 - languageName: node - linkType: hard - -"joycon@npm:^3.0.1, joycon@npm:^3.1.1": +"joycon@npm:^3.0.1": version: 3.1.1 resolution: "joycon@npm:3.1.1" checksum: 8003c9c3fc79c5c7602b1c7e9f7a2df2e9916f046b0dbad862aa589be78c15734d11beb9fe846f5e06138df22cb2ad29961b6a986ba81c4920ce2b15a7f11067 languageName: node linkType: hard -"js-beautify@npm:^1.6.14": - version: 1.14.11 - resolution: "js-beautify@npm:1.14.11" - dependencies: - config-chain: ^1.1.13 - editorconfig: ^1.0.3 - glob: ^10.3.3 - nopt: ^7.2.0 - bin: - css-beautify: js/bin/css-beautify.js - html-beautify: js/bin/html-beautify.js - js-beautify: js/bin/js-beautify.js - checksum: 92512b8dcc54330fe075569fd0226a1960da3fbb68f91e35dbfb110cc2b85e53e3ef17878c8be88b0888277bc5d51b1a692d72a00142d653ce7a8cbd48c66ee0 - languageName: node - linkType: hard - "js-cookie@npm:^2.2.1": version: 2.2.1 resolution: "js-cookie@npm:2.2.1" @@ -8704,24 +7858,6 @@ __metadata: languageName: node linkType: hard -"jsonwebtoken@npm:^9.0.1": - version: 9.0.2 - resolution: "jsonwebtoken@npm:9.0.2" - dependencies: - jws: ^3.2.2 - lodash.includes: ^4.3.0 - lodash.isboolean: ^3.0.3 - lodash.isinteger: ^4.0.4 - lodash.isnumber: ^3.0.3 - lodash.isplainobject: ^4.0.6 - lodash.isstring: ^4.0.1 - lodash.once: ^4.0.0 - ms: ^2.1.1 - semver: ^7.5.4 - checksum: fc739a6a8b33f1974f9772dca7f8493ca8df4cc31c5a09dcfdb7cff77447dcf22f4236fb2774ef3fe50df0abeb8e1c6f4c41eba82f500a804ab101e2fbc9d61a - languageName: node - linkType: hard - "jsprim@npm:^1.2.2": version: 1.4.2 resolution: "jsprim@npm:1.4.2" @@ -8746,21 +7882,6 @@ __metadata: languageName: node linkType: hard -"juice@npm:^9.0.0": - version: 9.1.0 - resolution: "juice@npm:9.1.0" - dependencies: - cheerio: ^1.0.0-rc.12 - commander: ^6.1.0 - mensch: ^0.3.4 - slick: ^1.12.2 - web-resource-inliner: ^6.0.1 - bin: - juice: bin/juice - checksum: 95f20fa183baa17360d7f03f2699f7cbc3476fb2e3a2d1d81d28f2ce1e5cd61a634a05cad26cfe83174c730ecbde18d8db9bc244b915741833fa6ce1c61c6864 - languageName: node - linkType: hard - "just-diff-apply@npm:^5.2.0": version: 5.5.0 resolution: "just-diff-apply@npm:5.5.0" @@ -8775,27 +7896,6 @@ __metadata: languageName: node linkType: hard -"jwa@npm:^1.4.1": - version: 1.4.1 - resolution: "jwa@npm:1.4.1" - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: ^5.0.1 - checksum: ff30ea7c2dcc61f3ed2098d868bf89d43701605090c5b21b5544b512843ec6fd9e028381a4dda466cbcdb885c2d1150f7c62e7168394ee07941b4098e1035e2f - languageName: node - linkType: hard - -"jws@npm:^3.2.2": - version: 3.2.2 - resolution: "jws@npm:3.2.2" - dependencies: - jwa: ^1.4.1 - safe-buffer: ^5.0.1 - checksum: f0213fe5b79344c56cd443428d8f65c16bf842dc8cb8f5aed693e1e91d79c20741663ad6eff07a6d2c433d1831acc9814e8d7bada6a0471fbb91d09ceb2bf5c2 - languageName: node - linkType: hard - "katex@npm:^0.15.3": version: 0.15.6 resolution: "katex@npm:0.15.6" @@ -8807,7 +7907,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.0.0, keyv@npm:^4.5.3": +"keyv@npm:^4.5.3": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -9196,20 +8296,6 @@ __metadata: languageName: node linkType: hard -"lodash.includes@npm:^4.3.0": - version: 4.3.0 - resolution: "lodash.includes@npm:4.3.0" - checksum: 71092c130515a67ab3bd928f57f6018434797c94def7f46aafa417771e455ce3a4834889f4267b17887d7f75297dfabd96231bf704fd2b8c5096dc4a913568b6 - languageName: node - linkType: hard - -"lodash.isboolean@npm:^3.0.3": - version: 3.0.3 - resolution: "lodash.isboolean@npm:3.0.3" - checksum: b70068b4a8b8837912b54052557b21fc4774174e3512ed3c5b94621e5aff5eb6c68089d0a386b7e801d679cd105d2e35417978a5e99071750aa2ed90bffd0250 - languageName: node - linkType: hard - "lodash.isfunction@npm:^3.0.9": version: 3.0.9 resolution: "lodash.isfunction@npm:3.0.9" @@ -9217,13 +8303,6 @@ __metadata: languageName: node linkType: hard -"lodash.isinteger@npm:^4.0.4": - version: 4.0.4 - resolution: "lodash.isinteger@npm:4.0.4" - checksum: 6034821b3fc61a2ffc34e7d5644bb50c5fd8f1c0121c554c21ac271911ee0c0502274852845005f8651d51e199ee2e0cfebfe40aaa49c7fe617f603a8a0b1691 - languageName: node - linkType: hard - "lodash.ismatch@npm:^4.4.0": version: 4.4.0 resolution: "lodash.ismatch@npm:4.4.0" @@ -9231,13 +8310,6 @@ __metadata: languageName: node linkType: hard -"lodash.isnumber@npm:^3.0.3": - version: 3.0.3 - resolution: "lodash.isnumber@npm:3.0.3" - checksum: 913784275b565346255e6ae6a6e30b760a0da70abc29f3e1f409081585875105138cda4a429ff02577e1bc0a7ae2a90e0a3079a37f3a04c3d6c5aaa532f4cab2 - languageName: node - linkType: hard - "lodash.isplainobject@npm:^4.0.6": version: 4.0.6 resolution: "lodash.isplainobject@npm:4.0.6" @@ -9280,13 +8352,6 @@ __metadata: languageName: node linkType: hard -"lodash.once@npm:^4.0.0": - version: 4.1.1 - resolution: "lodash.once@npm:4.1.1" - checksum: d768fa9f9b4e1dc6453be99b753906f58990e0c45e7b2ca5a3b40a33111e5d17f6edf2f768786e2716af90a8e78f8f91431ab8435f761fef00f9b0c256f6d245 - languageName: node - linkType: hard - "lodash.reduce@npm:^4.6.0": version: 4.6.0 resolution: "lodash.reduce@npm:4.6.0" @@ -9397,20 +8462,6 @@ __metadata: languageName: node linkType: hard -"lower-case@npm:^1.1.1": - version: 1.1.4 - resolution: "lower-case@npm:1.1.4" - checksum: 1ca9393b5eaef94a64e3f89e38b63d15bc7182a91171e6ad1550f51d710ec941540a065b274188f2e6b4576110cc2d11b50bc4bb7c603a040ddeb1db4ca95197 - languageName: node - linkType: hard - -"lowercase-keys@npm:^2.0.0": - version: 2.0.0 - resolution: "lowercase-keys@npm:2.0.0" - checksum: 24d7ebd56ccdf15ff529ca9e08863f3c54b0b9d1edb97a3ae1af34940ae666c01a1e6d200707bce730a8ef76cb57cc10e65f245ecaaf7e6bc8639f2fb460ac23 - languageName: node - linkType: hard - "lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": version: 10.0.3 resolution: "lru-cache@npm:10.0.3" @@ -9434,13 +8485,6 @@ __metadata: languageName: node linkType: hard -"luxon@npm:^3.2.1": - version: 3.4.4 - resolution: "luxon@npm:3.4.4" - checksum: 36c1f99c4796ee4bfddf7dc94fa87815add43ebc44c8934c924946260a58512f0fd2743a629302885df7f35ccbd2d13f178c15df046d0e3b6eb71db178f1c60c - languageName: node - linkType: hard - "magic-string@npm:^0.27.0": version: 0.27.0 resolution: "magic-string@npm:0.27.0" @@ -9847,20 +8891,6 @@ __metadata: languageName: node linkType: hard -"memory-pager@npm:^1.0.2": - version: 1.5.0 - resolution: "memory-pager@npm:1.5.0" - checksum: d1a2e684583ef55c61cd3a49101da645b11ad57014dfc565e0b43baa9004b743f7e4ab81493d8fff2ab24e9950987cc3209c94bcc4fc8d7e30a475489a1f15e9 - languageName: node - linkType: hard - -"mensch@npm:^0.3.4": - version: 0.3.4 - resolution: "mensch@npm:0.3.4" - checksum: eabb25d595b9bb7c067b932ea9c96f0c8154a4bb6c454a4edecef9f5c87652e345a40128741ed95905699c5a16ad1f6c7efd5f6dfc06e18128d74b569a4fb893 - languageName: node - linkType: hard - "meow@npm:^12.0.1": version: 12.1.1 resolution: "meow@npm:12.1.1" @@ -10243,25 +9273,6 @@ __metadata: languageName: node linkType: hard -"migrate-mongo@npm:^10.0.0": - version: 10.0.0 - resolution: "migrate-mongo@npm:10.0.0" - dependencies: - cli-table3: ^0.6.1 - commander: ^9.1.0 - date-fns: ^2.28.0 - fn-args: ^5.0.0 - fs-extra: ^10.0.1 - lodash: ^4.17.21 - p-each-series: ^2.2.0 - peerDependencies: - mongodb: ^4.4.1 || ^5.0.0 - bin: - migrate-mongo: bin/migrate-mongo.js - checksum: 0696db54624b01bc342793dc05be3b62a6cf5a22e23091bf779ed1d42cb9e0292c3130ecc2a1452c2b085a58dc43d7322185d2aa5e0d201da2de173b550bff4e - languageName: node - linkType: hard - "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -10278,15 +9289,6 @@ __metadata: languageName: node linkType: hard -"mime@npm:^2.4.6": - version: 2.6.0 - resolution: "mime@npm:2.6.0" - bin: - mime: cli.js - checksum: 1497ba7b9f6960694268a557eae24b743fd2923da46ec392b042469f4b901721ba0adcf8b0d3c2677839d0e243b209d76e5edcbd09cfdeffa2dfb6bb4df4b862 - languageName: node - linkType: hard - "mime@npm:^3.0.0": version: 3.0.0 resolution: "mime@npm:3.0.0" @@ -10310,29 +9312,6 @@ __metadata: languageName: node linkType: hard -"mimic-response@npm:^1.0.0": - version: 1.0.1 - resolution: "mimic-response@npm:1.0.1" - checksum: 034c78753b0e622bc03c983663b1cdf66d03861050e0c8606563d149bc2b02d63f62ce4d32be4ab50d0553ae0ffe647fc34d1f5281184c6e1e8cf4d85e8d9823 - languageName: node - linkType: hard - -"mimic-response@npm:^3.1.0": - version: 3.1.0 - resolution: "mimic-response@npm:3.1.0" - checksum: 25739fee32c17f433626bf19f016df9036b75b3d84a3046c7d156e72ec963dd29d7fc8a302f55a3d6c5a4ff24259676b15d915aad6480815a969ff2ec0836867 - languageName: node - linkType: hard - -"min-document@npm:^2.19.0": - version: 2.19.0 - resolution: "min-document@npm:2.19.0" - dependencies: - dom-walk: ^0.1.0 - checksum: da6437562ea2228041542a2384528e74e22d1daa1a4ec439c165abf0b9d8a63e17e3b8a6dc6e0c731845e85301198730426932a0e813d23f932ca668340c9623 - languageName: node - linkType: hard - "min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -10349,15 +9328,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.1": - version: 9.0.1 - resolution: "minimatch@npm:9.0.1" - dependencies: - brace-expansion: ^2.0.1 - checksum: 97f5f5284bb57dc65b9415dec7f17a0f6531a33572193991c60ff18450dcfad5c2dad24ffeaf60b5261dccd63aae58cc3306e2209d57e7f88c51295a532d8ec3 - languageName: node - linkType: hard - "minimatch@npm:^5.0.1": version: 5.1.6 resolution: "minimatch@npm:5.1.6" @@ -10387,7 +9357,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:~1.2.5": +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -10408,500 +9378,98 @@ __metadata: resolution: "minipass-fetch@npm:2.1.2" dependencies: encoding: ^0.1.13 - minipass: ^3.1.6 - minipass-sized: ^1.0.3 - minizlib: ^2.1.2 - dependenciesMeta: - encoding: - optional: true - checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91 - languageName: node - linkType: hard - -"minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" - dependencies: - encoding: ^0.1.13 - minipass: ^7.0.3 - minipass-sized: ^1.0.3 - minizlib: ^2.1.2 - dependenciesMeta: - encoding: - optional: true - checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: ^3.0.0 - checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf - languageName: node - linkType: hard - -"minipass-json-stream@npm:^1.0.1": - version: 1.0.1 - resolution: "minipass-json-stream@npm:1.0.1" - dependencies: - jsonparse: ^1.3.1 - minipass: ^3.0.0 - checksum: 791b696a27d1074c4c08dab1bf5a9f3201145c2933e428f45d880467bce12c60de4703203d2928de4b162d0ae77b0bb4b55f96cb846645800aa0eb4919b3e796 - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: ^3.0.0 - checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: ^3.0.0 - checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 - languageName: node - linkType: hard - -"minipass@npm:^3.0.0, minipass@npm:^3.1.1, minipass@npm:^3.1.6": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: ^4.0.0 - checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: ^3.0.0 - yallist: ^4.0.0 - checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 - languageName: node - linkType: hard - -"mjml-accordion@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-accordion@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 66212dcf89531da230115c786dec24194d8ec9a4c93bcc1cfdbac332be07678eee3b8479d46f155cb60bf13358edd5cd7e4d6538ad5f9a910cbee5bb6b450855 - languageName: node - linkType: hard - -"mjml-body@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-body@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 27388e15681bb25412a7123ae82559e6cb5586293aef3aa2cf57138bee401c1b53e84d8efacef2c9db4cb7bf8dc8cac741b7907ec11036f2b804178db511301c - languageName: node - linkType: hard - -"mjml-button@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-button@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 55fa3228476fbb17c51d63fbc9a18ce280c3246a69164bbd6d93f4670b3a9f93e985cece5958cc94ff0b60fbc199bd1382fd85d27aac0677517926ec8dd0ad6f - languageName: node - linkType: hard - -"mjml-carousel@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-carousel@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: db6d7847722ef1d4fd2b74aba04853156c729ba1a99e5565fbe5c32ed96733de1846fc41995505ec950de4953fa415586251c1e65f731725edd9d4b08b259e87 - languageName: node - linkType: hard - -"mjml-cli@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-cli@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - chokidar: ^3.0.0 - glob: ^7.1.1 - html-minifier: ^4.0.0 - js-beautify: ^1.6.14 - lodash: ^4.17.21 - mjml-core: 4.14.1 - mjml-migrate: 4.14.1 - mjml-parser-xml: 4.14.1 - mjml-validator: 4.13.0 - yargs: ^16.1.0 - bin: - mjml-cli: bin/mjml - checksum: ed3a08c68b6c5261e173674d1f1276b2cd636f2edc8713234a071befe919f9f9aa22e254480516d4b8d49eef22989017ce4327418c1c03fe08b004b6d1f8d136 - languageName: node - linkType: hard - -"mjml-column@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-column@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: a8eb4f321b9015ba8be96d08019502ada557fe3ba55413abf71b39a9ce209d0a3550ba03714a91b03b065af8b64582f6b3703b249f77c12bc1b54a499ac10ee2 - languageName: node - linkType: hard - -"mjml-core@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-core@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - cheerio: 1.0.0-rc.12 - detect-node: ^2.0.4 - html-minifier: ^4.0.0 - js-beautify: ^1.6.14 - juice: ^9.0.0 - lodash: ^4.17.21 - mjml-migrate: 4.14.1 - mjml-parser-xml: 4.14.1 - mjml-validator: 4.13.0 - checksum: fe46769b1746b1da90ddd39c584a6c8f7db80e125e079ce83cfd8ab4888e5abfff2933f573993926b36721de194b261c28f078b9316c395b185fd4098298c025 - languageName: node - linkType: hard - -"mjml-divider@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-divider@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: b44fab9de9751caf626ca6206b58c2a9ac7788c54c56d91cc892f77ed164a0fd2021422ef1019adb147a145873db499bb89f1518aa4326face1135acd8f61294 - languageName: node - linkType: hard - -"mjml-group@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-group@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 17cec7be9544ae32121cac12cf6dffd0a234bb2c14e2e72df230c52f1834f34fbd2df6ed15661491d0eee2c95dd7ad77e6048ca0ca012c9970d96bcfe8a4e77e - languageName: node - linkType: hard - -"mjml-head-attributes@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-attributes@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 93783e5ce4df95c745fee65cf2a4787eadbd548bb2d35f4c408d50cd4f81652061da4fcf54b4861db40bef115b60bb29f36faf6478033ad32e5e467415ec394a - languageName: node - linkType: hard - -"mjml-head-breakpoint@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-breakpoint@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: b52ea526f9291e0919ec82a7cc89e1e4d5a22c78280bc039b97648a3b938778d3bc7ff77b658a8a5d247c80327d2677f1591a5638039edc0d7c6f86670a1aeec - languageName: node - linkType: hard - -"mjml-head-font@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-font@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 3787977d042634ed338eb5d1be8612494a55419f568187c40517d3c53d57a93d3efd13c82c89d4a5b5c6456082bee12b6f682ededbc24a071600c9986a88ee94 - languageName: node - linkType: hard - -"mjml-head-html-attributes@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-html-attributes@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: a076f05954e09d7d8d721dc6931a1ecfcfa59126d4c7859c6278404d8e036b83f8eb72fd4285f367324d170bde7df64385ddf093b9f47cf5115fffd85756a510 - languageName: node - linkType: hard - -"mjml-head-preview@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-preview@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 9d8301458a93794695a1c50a16dbdd7914c008f0a89ee87be9d83f494966fb0aa51434549a6f183a014e34bfdc23795607bc33a33a1a4225882c8d0208fa3898 - languageName: node - linkType: hard - -"mjml-head-style@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-style@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 2e96180bd72656c70507f21a37f8cf3c0dc41709052af42e1161d77551df762f62d863635c18dff6d092bab9bd8c8c631c0a09b3c6dc25575f0693ee6627b7ba - languageName: node - linkType: hard - -"mjml-head-title@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-title@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 65dfe9cb5115a9cfe76851b9e5aabaaa30131e55a4346e9ec04bde3234897ffe1ab3e7bb37a695af44deffe4a869dee34668a3d87396ed50b923310fb9baebcd - languageName: node - linkType: hard - -"mjml-head@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: c83c930badb7ad0ee5771b13928d2c371aa9b70777393e32361fa356b534d1b282f5698e41dee8f947c687d28580e80b74bac2d3308970884e58152edc86bafd - languageName: node - linkType: hard - -"mjml-hero@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-hero@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 6c6ec8e5168709f09175d030c2a6fc7326f7a2e076cf09c0676e78bd941521e2c4295335bfdce8b5c31ea946a1925edcb780aced73b0dbfda40c07a463526c93 - languageName: node - linkType: hard - -"mjml-image@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-image@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 1ad0910300b115fcc42de6d642ce35b2a3593ac1a431498a2a2f3210733ff7c2e4bc33334abbd20f9854c77aa0f7c859928941fa6cb0bce190453f857e7c7f90 - languageName: node - linkType: hard - -"mjml-migrate@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-migrate@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - js-beautify: ^1.6.14 - lodash: ^4.17.21 - mjml-core: 4.14.1 - mjml-parser-xml: 4.14.1 - yargs: ^16.1.0 - bin: - migrate: lib/cli.js - checksum: 6710d100d79fd0b066cfd2fd0a5f7e6d7ccbf309a31039f162a22ff7b69c0540e550325560737270b205a3a3cd4562603e6bc4a44424ca973c44168741c3f388 - languageName: node - linkType: hard - -"mjml-navbar@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-navbar@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: b85ccb20a95575387b5ce65e317f9a25fe46c1d77bab506274d630950da6bcbec1034cf351887eb1aec10e6c0b8b926804fc20cbed99209de45d49ada736f969 + minipass: ^3.1.6 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91 languageName: node linkType: hard -"mjml-parser-xml@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-parser-xml@npm:4.14.1" +"minipass-fetch@npm:^3.0.0": + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" dependencies: - "@babel/runtime": ^7.14.6 - detect-node: 2.0.4 - htmlparser2: ^8.0.1 - lodash: ^4.17.15 - checksum: 839225d2d8c5b7c8a948ebe2a49afa8aa8f4e3651810b40df95d6f39da56ea6d62e2c4e5c55f96eb60d191233c0d2c77be0ee9cc861ffa5c3da032be56e0d96c - languageName: node - linkType: hard - -"mjml-preset-core@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-preset-core@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - mjml-accordion: 4.14.1 - mjml-body: 4.14.1 - mjml-button: 4.14.1 - mjml-carousel: 4.14.1 - mjml-column: 4.14.1 - mjml-divider: 4.14.1 - mjml-group: 4.14.1 - mjml-head: 4.14.1 - mjml-head-attributes: 4.14.1 - mjml-head-breakpoint: 4.14.1 - mjml-head-font: 4.14.1 - mjml-head-html-attributes: 4.14.1 - mjml-head-preview: 4.14.1 - mjml-head-style: 4.14.1 - mjml-head-title: 4.14.1 - mjml-hero: 4.14.1 - mjml-image: 4.14.1 - mjml-navbar: 4.14.1 - mjml-raw: 4.14.1 - mjml-section: 4.14.1 - mjml-social: 4.14.1 - mjml-spacer: 4.14.1 - mjml-table: 4.14.1 - mjml-text: 4.14.1 - mjml-wrapper: 4.14.1 - checksum: 86852c543c138fcafecd461ccecd03c36b0ac573a644fe47a164b8f94465c33eee25c815e6cb17a85bd947bccd21ffb700023a22d1f39e5540ba9b663c96e7ce - languageName: node - linkType: hard - -"mjml-raw@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-raw@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 65721432a89653644ae7e451e5a09d5168e6a69900f73823b74803ac4f4ff148ee4654db916e770e9e7a4e51cb83222c95b15b0220f21d96eeb9eb1a8571be7d + encoding: ^0.1.13 + minipass: ^7.0.3 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a languageName: node linkType: hard -"mjml-section@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-section@npm:4.14.1" +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: f4b2ba3fa916193635b273d482a23e6f2f2969d01b5517e62d505ef5b6260e404bd2df3252ebd5926c1d5dc79f33cac8ceab19c161cf8435c3a23148c0296a15 + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf languageName: node linkType: hard -"mjml-social@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-social@npm:4.14.1" +"minipass-json-stream@npm:^1.0.1": + version: 1.0.1 + resolution: "minipass-json-stream@npm:1.0.1" dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 4d493dcb133beb6361cc5b6ff5799ef8456e39fd89f60d1c8ecc8767eb2fcfedf5f0a253dfafa543c6c3a32a798cb3e009b59e6588fdce5726b057435cf5d3a6 + jsonparse: ^1.3.1 + minipass: ^3.0.0 + checksum: 791b696a27d1074c4c08dab1bf5a9f3201145c2933e428f45d880467bce12c60de4703203d2928de4b162d0ae77b0bb4b55f96cb846645800aa0eb4919b3e796 languageName: node linkType: hard -"mjml-spacer@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-spacer@npm:4.14.1" +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 93bf08f18da4a6593ded0675d32d0b2599d8fa9b00a3f3c0d90803106611f09a48efff803f82e740e27c8e5e56a36a40c66c87045ca7090ca5685762f0fe9382 + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b languageName: node linkType: hard -"mjml-table@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-table@npm:4.14.1" +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: f7fc1f648a112b8bab5209e9a3200926b1c10b39acc90f691e6b2e6d75a642ebf2f8f603b72676bd3490c3afaad97d06f1a64503dd971695f431760436317b26 + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 languageName: node linkType: hard -"mjml-text@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-text@npm:4.14.1" +"minipass@npm:^3.0.0, minipass@npm:^3.1.1, minipass@npm:^3.1.6": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 16133c363813a4ec5bef06fbd34789a59d06206f78c43e43f1979bb326169b9f0809c4ddf651a05ae8ea4b295dcce6ad80d6c696b628832a5357d3bb532a2d5d + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 languageName: node linkType: hard -"mjml-validator@npm:4.13.0": - version: 4.13.0 - resolution: "mjml-validator@npm:4.13.0" - dependencies: - "@babel/runtime": ^7.14.6 - checksum: 40397cc664ee0e1ad884ddef30e2ab1cb3b14bb3fb1730e9ba8d7a786c25a260726b4bb70bae7094aa4177a369fd46bd2bf7f8e744f9cdecd0c3ceb8881b075e +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea languageName: node linkType: hard -"mjml-wrapper@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-wrapper@npm:4.14.1" - dependencies: - "@babel/runtime": ^7.14.6 - lodash: ^4.17.21 - mjml-core: 4.14.1 - mjml-section: 4.14.1 - checksum: c3421fe6d783b4dfe617b37eae21aa3ff6e345ad06e18e8aeddd91e70bea75d277004feaf39d9af298e6e3ee550553df5110121d4486e1610ad51ae61a5ddf07 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 languageName: node linkType: hard -"mjml@npm:^4.14.1": - version: 4.14.1 - resolution: "mjml@npm:4.14.1" +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" dependencies: - "@babel/runtime": ^7.14.6 - mjml-cli: 4.14.1 - mjml-core: 4.14.1 - mjml-migrate: 4.14.1 - mjml-preset-core: 4.14.1 - mjml-validator: 4.13.0 - bin: - mjml: bin/mjml - checksum: 48906b077ea7283f77cec0baec422ebee133a5a2ea2c727c31e35f4b4e56894ef3134fb317704c12e4bc40632321779df19b950555bc49d188675e84dca7a826 + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 languageName: node linkType: hard @@ -10962,7 +9530,6 @@ __metadata: eslint-plugin-simple-import-sort: ^10.0.0 eslint-plugin-unused-imports: ^2.0.0 eslint-plugin-zod: ^1.4.0 - global: 4.4.0 husky: ^8.0.3 lint-staged: ^14.0.1 node-talisman: ^1.29.10 @@ -10998,50 +9565,6 @@ __metadata: languageName: node linkType: hard -"mongodb-connection-string-url@npm:^3.0.0": - version: 3.0.0 - resolution: "mongodb-connection-string-url@npm:3.0.0" - dependencies: - "@types/whatwg-url": ^11.0.2 - whatwg-url: ^13.0.0 - checksum: 9d4885377345b14e2ba2ee63cb3085364a01aeae3aca622bbd568e7761caa58fdc664528f19f125c762cff230c9349f99e98396dd2271a4260286cf241a8c477 - languageName: node - linkType: hard - -"mongodb@npm:^6.1.0": - version: 6.3.0 - resolution: "mongodb@npm:6.3.0" - dependencies: - "@mongodb-js/saslprep": ^1.1.0 - bson: ^6.2.0 - mongodb-connection-string-url: ^3.0.0 - peerDependencies: - "@aws-sdk/credential-providers": ^3.188.0 - "@mongodb-js/zstd": ^1.1.0 - gcp-metadata: ^5.2.0 - kerberos: ^2.0.1 - mongodb-client-encryption: ">=6.0.0 <7" - snappy: ^7.2.2 - socks: ^2.7.1 - peerDependenciesMeta: - "@aws-sdk/credential-providers": - optional: true - "@mongodb-js/zstd": - optional: true - gcp-metadata: - optional: true - kerberos: - optional: true - mongodb-client-encryption: - optional: true - snappy: - optional: true - socks: - optional: true - checksum: ebc5d9dbd1299321b6873e86eb4ea635316f97450644811db24ce2b01432b1c641def864facf2eab6f0c0c5c360c318108ea5555142f55177ca4c33991c6d7c4 - languageName: node - linkType: hard - "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -11056,16 +9579,6 @@ __metadata: languageName: node linkType: hard -"multipipe@npm:^1.0.2": - version: 1.0.2 - resolution: "multipipe@npm:1.0.2" - dependencies: - duplexer2: ^0.1.2 - object-assign: ^4.1.0 - checksum: 99cf8934714da7f9ce03e1f0a99621a41443217d80849c62e22b31b6ac356b9acd22f41e555fd7a759f1c7c9d3273e7abff2fb82dff8285f00a6a1022727e4ab - languageName: node - linkType: hard - "mute-stream@npm:~1.0.0": version: 1.0.0 resolution: "mute-stream@npm:1.0.0" @@ -11242,26 +9755,6 @@ __metadata: languageName: node linkType: hard -"no-case@npm:^2.2.0": - version: 2.3.2 - resolution: "no-case@npm:2.3.2" - dependencies: - lower-case: ^1.1.1 - checksum: 856487731936fef44377ca74fdc5076464aba2e0734b56a4aa2b2a23d5b154806b591b9b2465faa59bb982e2b5c9391e3685400957fb4eeb38f480525adcf3dd - languageName: node - linkType: hard - -"nock@npm:^13.3.3": - version: 13.3.8 - resolution: "nock@npm:13.3.8" - dependencies: - debug: ^4.1.0 - json-stringify-safe: ^5.0.1 - propagate: ^2.0.0 - checksum: 98f7d9d1c6b4fad560d7f1033705f9a0318e288060c10e36973d1798d6c824fee1f23a9ecbb1118bf70068f58bb04eaa50c5d046f5cf0ceaf4a2dc76fe7a82b2 - languageName: node - linkType: hard - "node-emoji@npm:^1.11.0": version: 1.11.0 resolution: "node-emoji@npm:1.11.0" @@ -11271,7 +9764,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.3.0, node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.7": +"node-fetch@npm:^2.3.0, node-fetch@npm:^2.6.7": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -11340,22 +9833,6 @@ __metadata: languageName: node linkType: hard -"nodemailer-html-to-text@npm:^3.2.0": - version: 3.2.0 - resolution: "nodemailer-html-to-text@npm:3.2.0" - dependencies: - html-to-text: 7.1.1 - checksum: 5c6335b2fafdac0e11557e1d4ce951387b9acd7b0972c8f6dad4df8b9a98d9ec877b40b9f3a0783492d68c8fe3789585e25e971b80b1684a8fba31d3044cedc0 - languageName: node - linkType: hard - -"nodemailer@npm:^6.9.4": - version: 6.9.7 - resolution: "nodemailer@npm:6.9.7" - checksum: 0cf66d27aed3bd2cbdff9939402cec3d2119c31b2b9ff4af3bcd59f48287ea75b90c0ce2cd9eb0df838164972cd25581b4b723c91fd673e2608bcb28445ccb1b - languageName: node - linkType: hard - "nopt@npm:^6.0.0": version: 6.0.0 resolution: "nopt@npm:6.0.0" @@ -11433,13 +9910,6 @@ __metadata: languageName: node linkType: hard -"normalize-url@npm:^6.0.1": - version: 6.1.0 - resolution: "normalize-url@npm:6.1.0" - checksum: 4a4944631173e7d521d6b80e4c85ccaeceb2870f315584fa30121f505a6dfd86439c5e3fdd8cd9e0e291290c41d0c3599f0cb12ab356722ed242584c30348e50 - languageName: node - linkType: hard - "normalize-url@npm:^7.0.3": version: 7.2.0 resolution: "normalize-url@npm:7.2.0" @@ -11454,18 +9924,6 @@ __metadata: languageName: node linkType: hard -"notion-client@npm:^6.16.0": - version: 6.16.0 - resolution: "notion-client@npm:6.16.0" - dependencies: - got: ^11.8.1 - notion-types: ^6.16.0 - notion-utils: ^6.16.0 - p-map: ^5.3.0 - checksum: 6e8b63e91eab1831cead53416ba68ffd03ec947a16b4995395a17c9ff7a6b9d47265d94f8f4a392b22e74c1edd64947ca6e3f1c334c5151815799cdb75b4a2f9 - languageName: node - linkType: hard - "notion-types@npm:^6.16.0": version: 6.16.0 resolution: "notion-types@npm:6.16.0" @@ -11706,15 +10164,6 @@ __metadata: languageName: node linkType: hard -"nth-check@npm:^2.0.1": - version: 2.1.1 - resolution: "nth-check@npm:2.1.1" - dependencies: - boolbase: ^1.0.0 - checksum: 5afc3dafcd1573b08877ca8e6148c52abd565f1d06b1eb08caf982e3fa289a82f2cae697ffb55b5021e146d60443f1590a5d6b944844e944714a5b549675bcd3 - languageName: node - linkType: hard - "oauth-sign@npm:~0.9.0": version: 0.9.0 resolution: "oauth-sign@npm:0.9.0" @@ -11722,7 +10171,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": +"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f @@ -11750,13 +10199,6 @@ __metadata: languageName: node linkType: hard -"object-keys@npm:~0.4.0": - version: 0.4.0 - resolution: "object-keys@npm:0.4.0" - checksum: 1be3ebe9b48c0d5eda8e4a30657d887a748cb42435e0e2eaf49faf557bdd602cd2b7558b8ce90a4eb2b8592d16b875a1900bce859cbb0f35b21c67e11a45313c - languageName: node - linkType: hard - "object.assign@npm:^4.1.4": version: 4.1.4 resolution: "object.assign@npm:4.1.4" @@ -11838,7 +10280,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -11886,13 +10328,6 @@ __metadata: languageName: node linkType: hard -"p-cancelable@npm:^2.0.0": - version: 2.1.1 - resolution: "p-cancelable@npm:2.1.1" - checksum: 3dba12b4fb4a1e3e34524535c7858fc82381bbbd0f247cc32dedc4018592a3950ce66b106d0880b4ec4c2d8d6576f98ca885dc1d7d0f274d1370be20e9523ddf - languageName: node - linkType: hard - "p-defer@npm:^1.0.0": version: 1.0.0 resolution: "p-defer@npm:1.0.0" @@ -11900,13 +10335,6 @@ __metadata: languageName: node linkType: hard -"p-each-series@npm:^2.2.0": - version: 2.2.0 - resolution: "p-each-series@npm:2.2.0" - checksum: 5fbe2f1f1966f55833bd401fe36f7afe410707d5e9fb6032c6dde8aa716d50521c3bb201fdb584130569b5941d5e84993e09e0b3f76a474288e0ede8f632983c - languageName: node - linkType: hard - "p-each-series@npm:^3.0.0": version: 3.0.0 resolution: "p-each-series@npm:3.0.0" @@ -12011,7 +10439,7 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^5.1.0, p-map@npm:^5.3.0": +"p-map@npm:^5.1.0": version: 5.5.0 resolution: "p-map@npm:5.5.0" dependencies: @@ -12093,15 +10521,6 @@ __metadata: languageName: node linkType: hard -"param-case@npm:^2.1.1": - version: 2.1.1 - resolution: "param-case@npm:2.1.1" - dependencies: - no-case: ^2.2.0 - checksum: 3a63dcb8d8dc7995a612de061afdc7bb6fe7bd0e6db994db8d4cae999ed879859fd24389090e1a0d93f4c9207ebf8c048c870f468a3f4767161753e03cb9ab58 - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -12187,25 +10606,6 @@ __metadata: languageName: node linkType: hard -"parse5-htmlparser2-tree-adapter@npm:^7.0.0": - version: 7.0.0 - resolution: "parse5-htmlparser2-tree-adapter@npm:7.0.0" - dependencies: - domhandler: ^5.0.2 - parse5: ^7.0.0 - checksum: fc5d01e07733142a1baf81de5c2a9c41426c04b7ab29dd218acb80cd34a63177c90aff4a4aee66cf9f1d0aeecff1389adb7452ad6f8af0a5888e3e9ad6ef733d - languageName: node - linkType: hard - -"parse5@npm:^7.0.0": - version: 7.1.2 - resolution: "parse5@npm:7.1.2" - dependencies: - entities: ^4.4.0 - checksum: 59465dd05eb4c5ec87b76173d1c596e152a10e290b7abcda1aecf0f33be49646ea74840c69af975d7887543ea45564801736356c568d6b5e71792fd0f4055713 - languageName: node - linkType: hard - "path-exists@npm:^3.0.0": version: 3.0.0 resolution: "path-exists@npm:3.0.0" @@ -12354,7 +10754,7 @@ __metadata: languageName: node linkType: hard -"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:v1.1.0": +"pino-abstract-transport@npm:v1.1.0": version: 1.1.0 resolution: "pino-abstract-transport@npm:1.1.0" dependencies: @@ -12364,30 +10764,6 @@ __metadata: languageName: node linkType: hard -"pino-pretty@npm:^10.2.3": - version: 10.2.3 - resolution: "pino-pretty@npm:10.2.3" - dependencies: - colorette: ^2.0.7 - dateformat: ^4.6.3 - fast-copy: ^3.0.0 - fast-safe-stringify: ^2.1.1 - help-me: ^4.0.1 - joycon: ^3.1.1 - minimist: ^1.2.6 - on-exit-leak-free: ^2.1.0 - pino-abstract-transport: ^1.0.0 - pump: ^3.0.0 - readable-stream: ^4.0.0 - secure-json-parse: ^2.4.0 - sonic-boom: ^3.0.0 - strip-json-comments: ^3.1.1 - bin: - pino-pretty: bin.js - checksum: 9182886855515000df2ef381762c69fc29dbdd9014a76839cc3d8a7a94ac96d4ce17423adb9ddd61eae78986bb0ff3a1d9e6e7aa55476c096a3dd4a0c89440e8 - languageName: node - linkType: hard - "pino-std-serializers@npm:^6.0.0": version: 6.2.2 resolution: "pino-std-serializers@npm:6.2.2" @@ -12603,13 +10979,6 @@ __metadata: languageName: node linkType: hard -"propagate@npm:^2.0.0": - version: 2.0.1 - resolution: "propagate@npm:2.0.1" - checksum: c4febaee2be0979e82fb6b3727878fd122a98d64a7fa3c9d09b0576751b88514a9e9275b1b92e76b364d488f508e223bd7e1dcdc616be4cdda876072fbc2a96c - languageName: node - linkType: hard - "property-expr@npm:^2.0.5": version: 2.0.6 resolution: "property-expr@npm:2.0.6" @@ -12655,17 +11024,7 @@ __metadata: languageName: node linkType: hard -"pump@npm:^3.0.0": - version: 3.0.0 - resolution: "pump@npm:3.0.0" - dependencies: - end-of-stream: ^1.1.0 - once: ^1.3.1 - checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.0": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 @@ -12720,13 +11079,6 @@ __metadata: languageName: node linkType: hard -"quick-lru@npm:^5.1.1": - version: 5.1.1 - resolution: "quick-lru@npm:5.1.1" - checksum: a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed - languageName: node - linkType: hard - "rambda@npm:^7.4.0": version: 7.5.0 resolution: "rambda@npm:7.5.0" @@ -13012,7 +11364,7 @@ __metadata: languageName: node linkType: hard -"react@npm:18.2.0, react@npm:^18.2.0": +"react@npm:^18.2.0": version: 18.2.0 resolution: "react@npm:18.2.0" dependencies: @@ -13144,18 +11496,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:~1.0.17, readable-stream@npm:~1.0.27-1": - version: 1.0.34 - resolution: "readable-stream@npm:1.0.34" - dependencies: - core-util-is: ~1.0.0 - inherits: ~2.0.1 - isarray: 0.0.1 - string_decoder: ~0.10.x - checksum: 85042c537e4f067daa1448a7e257a201070bfec3dd2706abdbd8ebc7f3418eb4d3ed4b8e5af63e2544d69f88ab09c28d5da3c0b77dc76185fddd189a59863b60 - languageName: node - linkType: hard - "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -13255,13 +11595,6 @@ __metadata: languageName: node linkType: hard -"relateurl@npm:^0.2.7": - version: 0.2.7 - resolution: "relateurl@npm:0.2.7" - checksum: 5891e792eae1dfc3da91c6fda76d6c3de0333a60aa5ad848982ebb6dccaa06e86385fb1235a1582c680a3d445d31be01c6bfc0804ebbcab5aaf53fa856fde6b6 - languageName: node - linkType: hard - "remark-gfm@npm:^1.0.0": version: 1.0.0 resolution: "remark-gfm@npm:1.0.0" @@ -13364,13 +11697,6 @@ __metadata: languageName: node linkType: hard -"reselect@npm:^4.1.8": - version: 4.1.8 - resolution: "reselect@npm:4.1.8" - checksum: a4ac87cedab198769a29be92bc221c32da76cfdad6911eda67b4d3e7136dca86208c3b210e31632eae31ebd2cded18596f0dd230d3ccc9e978df22f233b5583e - languageName: node - linkType: hard - "resize-observer-polyfill@npm:^1.5.1": version: 1.5.1 resolution: "resize-observer-polyfill@npm:1.5.1" @@ -13378,13 +11704,6 @@ __metadata: languageName: node linkType: hard -"resolve-alpn@npm:^1.0.0": - version: 1.2.1 - resolution: "resolve-alpn@npm:1.2.1" - checksum: f558071fcb2c60b04054c99aebd572a2af97ef64128d59bef7ab73bd50d896a222a056de40ffc545b633d99b304c259ea9d0c06830d5c867c34f0bfa60b8eae0 - languageName: node - linkType: hard - "resolve-from@npm:5.0.0, resolve-from@npm:^5.0.0": version: 5.0.0 resolution: "resolve-from@npm:5.0.0" @@ -13467,15 +11786,6 @@ __metadata: languageName: node linkType: hard -"responselike@npm:^2.0.0": - version: 2.0.1 - resolution: "responselike@npm:2.0.1" - dependencies: - lowercase-keys: ^2.0.0 - checksum: b122535466e9c97b55e69c7f18e2be0ce3823c5d47ee8de0d9c0b114aa55741c6db8bfbfce3766a94d1272e61bfb1ebf0a15e9310ac5629fbb7446a861b4fd3a - languageName: node - linkType: hard - "restore-cursor@npm:^4.0.0": version: 4.0.0 resolution: "restore-cursor@npm:4.0.0" @@ -13847,53 +12157,30 @@ __metadata: version: 0.0.0-use.local resolution: "server@workspace:server" dependencies: - "@fastify/auth": ^4.4.0 "@fastify/cookie": ^9.1.0 "@fastify/cors": ^8.4.1 "@fastify/multipart": ^8.0.0 - "@fastify/swagger": ^8.12.0 - "@fastify/swagger-ui": ^1.10.1 "@hapi/boom": ^10.0.1 "@immobiliarelabs/fastify-sentry": ^7.1.1 "@sentry/integrations": ^7.77.0 "@sentry/node": ^7.77.0 - "@sentry/tracing": ^7.77.0 "@types/adm-zip": ^0.5.5 "@types/bunyan": ^1.8.8 "@types/bunyan-prettystream": ^0.1.32 - "@types/ejs": ^3.1.2 - "@types/jsonwebtoken": ^9.0.2 "@types/lodash-es": ^4.17.8 - "@types/migrate-mongo": ^10.0.0 - "@types/mjml": ^4.7.1 - "@types/nodemailer": ^6.4.9 - "@types/nodemailer-html-to-text": ^3.1.0 adm-zip: ^0.5.12 axios: ^1.5.1 axios-cache-interceptor: ^1.3.2 - axios-retry: ^3.8.0 bunyan: ^1.8.15 bunyan-prettystream: ^0.1.3 commander: ^10.0.1 - cron-parser: ^4.9.0 - csv-parse: ^5.4.0 - date-fns: ^2.30.0 dotenv: ^16.4.5 - ejs: ^3.1.9 env-var: ^7.3.1 fastify: ^4.21.0 fastify-type-provider-zod: ^1.1.9 - job-processor: ^1.4.7 - jsonwebtoken: ^9.0.1 lil-http-terminator: ^1.2.3 lodash-es: ^4.17.21 - migrate-mongo: ^10.0.0 - mjml: ^4.14.1 - nock: ^13.3.3 - nodemailer: ^6.9.4 - nodemailer-html-to-text: ^3.2.0 pdf-lib: ^1.17.1 - pino-pretty: ^10.2.3 query-string: ^9.0.0 rate-limiter-flexible: ^2.4.2 shared: "workspace:*" @@ -13959,9 +12246,7 @@ __metadata: version: 0.0.0-use.local resolution: "shared@workspace:shared" dependencies: - bson: ^5.4.0 - lodash-es: ^4.17.21 - react: 18.2.0 + date-fns: ^2.30.0 type-fest: ^4.2.0 typescript: ^5.1.6 zod: ^3.22.1 @@ -14081,13 +12366,6 @@ __metadata: languageName: node linkType: hard -"slick@npm:^1.12.2": - version: 1.12.2 - resolution: "slick@npm:1.12.2" - checksum: 02b586dac1ce12db4e6d3b89e61962e6e07966875b8099ba1d6fac2faa8c88f37450293c27706f296556e4698b9e139bfee4055b845a7c266eca4650609d7603 - languageName: node - linkType: hard - "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -14127,7 +12405,7 @@ __metadata: languageName: node linkType: hard -"sonic-boom@npm:^3.0.0, sonic-boom@npm:^3.7.0": +"sonic-boom@npm:^3.7.0": version: 3.7.0 resolution: "sonic-boom@npm:3.7.0" dependencies: @@ -14166,7 +12444,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.1, source-map@npm:~0.6.0": +"source-map@npm:^0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 @@ -14180,15 +12458,6 @@ __metadata: languageName: node linkType: hard -"sparse-bitfield@npm:^3.0.3": - version: 3.0.3 - resolution: "sparse-bitfield@npm:3.0.3" - dependencies: - memory-pager: ^1.0.2 - checksum: 174da88dbbcc783d5dbd26921931cc83830280b8055fb05333786ebe6fc015b9601b24972b3d55920dd2d9f5fb120576fbfa2469b08e5222c9cadf3f05210aab - languageName: node - linkType: hard - "spawn-error-forwarder@npm:~1.0.0": version: 1.0.0 resolution: "spawn-error-forwarder@npm:1.0.0" @@ -14489,13 +12758,6 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:~0.10.x": - version: 0.10.31 - resolution: "string_decoder@npm:0.10.31" - checksum: fe00f8e303647e5db919948ccb5ce0da7dea209ab54702894dd0c664edd98e5d4df4b80d6fabf7b9e92b237359d21136c95bf068b2f7760b772ca974ba970202 - languageName: node - linkType: hard - "string_decoder@npm:~1.1.1": version: 1.1.1 resolution: "string_decoder@npm:1.1.1" @@ -14807,16 +13069,6 @@ __metadata: languageName: node linkType: hard -"through2@npm:~0.4.1": - version: 0.4.2 - resolution: "through2@npm:0.4.2" - dependencies: - readable-stream: ~1.0.17 - xtend: ~2.1.1 - checksum: 50e41d272db4a74b10a62b7e92eeeb8d30e426a7a8a772cd85fac0f8e21d92c6e5cb5012d7db5f7a20f6e147e1f14f87062058c77b05bc9d463ae4d8b3eb1e42 - languageName: node - linkType: hard - "through2@npm:~2.0.0": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -14827,7 +13079,7 @@ __metadata: languageName: node linkType: hard -"through@npm:2, through@npm:>=2.2.7 <3, through@npm:^2.3.8": +"through@npm:2, through@npm:>=2.2.7 <3": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd @@ -14946,15 +13198,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^4.1.1": - version: 4.1.1 - resolution: "tr46@npm:4.1.1" - dependencies: - punycode: ^2.3.0 - checksum: aeeb821ac2cd792e63ec84888b4fd6598ac6ed75d861579e21a5cf9d4ee78b2c6b94e7d45036f2ca2088bc85b9b46560ad23c4482979421063b24137349dbd96 - languageName: node - linkType: hard - "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -15348,7 +13591,7 @@ __metadata: languageName: node linkType: hard -"uglify-js@npm:^3.1.4, uglify-js@npm:^3.5.1": +"uglify-js@npm:^3.1.4": version: 3.17.4 resolution: "uglify-js@npm:3.17.4" bin: @@ -15363,10 +13606,8 @@ __metadata: dependencies: "@codegouvfr/react-dsfr": ^0.75.7 "@emotion/react": ^11.11.1 - "@emotion/server": ^11.11.0 "@emotion/styled": ^11.11.0 "@mui/material": ^5.14.8 - "@mui/x-data-grid": ^6.13.0 "@sentry/integrations": ^7.81.1 "@sentry/nextjs": ^7.64.0 "@tanstack/react-query": ^4.32.6 @@ -15377,8 +13618,6 @@ __metadata: lodash-es: ^4.17.21 next: ^13.4.17 next-plausible: ^3.10.2 - notion-client: ^6.16.0 - notion-types: ^6.16.0 react: ^18.2.0 react-dom: ^18.2.0 react-hook-form: ^7.45.4 @@ -15621,13 +13860,6 @@ __metadata: languageName: node linkType: hard -"upper-case@npm:^1.1.1": - version: 1.1.3 - resolution: "upper-case@npm:1.1.3" - checksum: 991c845de75fa56e5ad983f15e58494dd77b77cadd79d273cc11e8da400067e9881ae1a52b312aed79b3d754496e2e0712e08d22eae799e35c7f9ba6f3d8a85d - languageName: node - linkType: hard - "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -15687,13 +13919,6 @@ __metadata: languageName: node linkType: hard -"valid-data-url@npm:^3.0.0": - version: 3.0.1 - resolution: "valid-data-url@npm:3.0.1" - checksum: 06584294fb4c9550f0aaa56470f8d748f4ebfc3ed230707db5559754719a66fc37f299b5a79b914375b8198d90f8a51e0401375391938caf8dc8e442308aab9e - languageName: node - linkType: hard - "validate-npm-package-license@npm:^3.0.1, validate-npm-package-license@npm:^3.0.4": version: 3.0.4 resolution: "validate-npm-package-license@npm:3.0.4" @@ -15934,20 +14159,6 @@ __metadata: languageName: node linkType: hard -"web-resource-inliner@npm:^6.0.1": - version: 6.0.1 - resolution: "web-resource-inliner@npm:6.0.1" - dependencies: - ansi-colors: ^4.1.1 - escape-goat: ^3.0.0 - htmlparser2: ^5.0.0 - mime: ^2.4.6 - node-fetch: ^2.6.0 - valid-data-url: ^3.0.0 - checksum: 17d9e53a6e5f07361abc584b6bb2bb8470978be580f8b5cdcab5998507ffccf5fb645616d3fe1550965d2db497f4a5cdc1ea1460c9cf464de315751962708ecc - languageName: node - linkType: hard - "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" @@ -15962,13 +14173,6 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^7.0.0": - version: 7.0.0 - resolution: "webidl-conversions@npm:7.0.0" - checksum: f05588567a2a76428515333eff87200fae6c83c3948a7482ebb109562971e77ef6dc49749afa58abb993391227c5697b3ecca52018793e0cb4620a48f10bd21b - languageName: node - linkType: hard - "webpack-sources@npm:^2.0.0 || ^3.0.0": version: 3.2.3 resolution: "webpack-sources@npm:3.2.3" @@ -15976,16 +14180,6 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^13.0.0": - version: 13.0.0 - resolution: "whatwg-url@npm:13.0.0" - dependencies: - tr46: ^4.1.1 - webidl-conversions: ^7.0.0 - checksum: 7f69272a1bfd5f0d994988b9e234e35d21071a9bffe0d6fd4477d295552665c566b176ff8e0251a0a79c61c5a67a7a392e248aae5887d7e22bdff0125209e26b - languageName: node - linkType: hard - "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -16165,15 +14359,6 @@ __metadata: languageName: node linkType: hard -"xtend@npm:~2.1.1": - version: 2.1.2 - resolution: "xtend@npm:2.1.2" - dependencies: - object-keys: ~0.4.0 - checksum: a8b79f31502c163205984eaa2b196051cd2fab0882b49758e30f2f9018255bc6c462e32a090bf3385d1bda04755ad8cc0052a09e049b0038f49eb9b950d9c447 - languageName: node - linkType: hard - "xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" @@ -16216,7 +14401,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": +"yargs-parser@npm:^20.2.3": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 @@ -16230,21 +14415,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^16.1.0": - version: 16.2.0 - resolution: "yargs@npm:16.2.0" - dependencies: - cliui: ^7.0.2 - escalade: ^3.1.1 - get-caller-file: ^2.0.5 - require-directory: ^2.1.1 - string-width: ^4.2.0 - y18n: ^5.0.5 - yargs-parser: ^20.2.2 - checksum: b14afbb51e3251a204d81937c86a7e9d4bdbf9a2bcee38226c900d00f522969ab675703bee2a6f99f8e20103f608382936034e64d921b74df82b63c07c5e8f59 - languageName: node - linkType: hard - "yargs@npm:^17.0.0, yargs@npm:^17.5.1": version: 17.7.2 resolution: "yargs@npm:17.7.2"