From d3d9866c2d47ff3e4aadca0099e4f8176af6c217 Mon Sep 17 00:00:00 2001 From: Kevin Barnoin Date: Sat, 29 Jun 2024 06:48:56 +0200 Subject: [PATCH] feat: migration preparation & global package upgrade for mongodb V7 (#1281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add mongodb utils * feat: add decriptor export model * feat: comment awaiting features * fix: remove duplicate collection name * feat: prepare models export * fix: sort and remove unused * feat: prepare server switch * fix: dedupe * feat: add indexes creation jobs * fix: comment * feat: update createIndex function * feat: prepare db switch for tests * chore: skip test for now * feat: update package & connector * fix: shared * fix: typing p1 * fix: typing p2 * feat: update mongodb shared * fix: revert * fix: bson version * fix: zod version + add & export zod-mongodb-schema to shared * feat: update mongodb driver to match bson * fix: typecheck * feat: update zod ui * fix: zod typing * feat: update openapi snapshot * feat: update route & snapshot * fix: test * fix: dedupe * fix: unskip test * fix: missing _id in pointgeometry definition * fix: _id geopoint can be nullish at creation * fix: remove _id directly from schema * fix: remove _id from definition * fix: bson compatibility error * fix: start jobs after mongoose * fix: mongodb connection * fix: admin flow activate/desactivate * fix: user validation flow * fix: admin get user * fix: simplification du typage de l'api getDbCollection (#1292) * fix: simplification du typage de l'api getDbCollection * fix: ajout de tous les models * fix: update job statut from admin * feat: remove log & update /user/opco mongo query * fix: Lbac 2259 migration mongodb lot 3 (#1296) * fix: migration mongo lot 3 * fix: tsconfig + update * fix: update * fix: update * fix: suppression du script server/src/jobs/seed/ficheMetierRomev4/ficheMetierRomev4.ts * feat: lbac 2257: migration appels mongodb lot1 (#1294) * feat: migrate apicalls * feat: add new schema validation * feat: migrate credentials * feat: migrate anonymization * feat: migrate customemailetfa * feat: migrate lbacompanylegacies * feat: migrate lbacompanies * feat: migrate cfas * feat: migrate diplomesmetiers * feat: migrate domainesmetiers * feat: migrate application p1 * feat: migrate appointment p1 * fix: return new documen t * fix: projection * feat: migrate appointment p2 * feat: migrate application p2 * fix: snapshot * fix: logic * fix: buildtopic job_title awaited type * fix: snapshot * fix: suppression de INewAppointment * feat: update test setup * fix: core route + test --------- Co-authored-by: Rémy Auricoste * feat: remove application model * feat: LBA-2258 lot 2 (#1293) Collections : "etablissements" "eligible_trainings_for_appointments" "eligible_trainings_for_appointments_histories" "emailblacklists" "entreprises" "formationcatalogues" "geolocations" "internalJobs" "opcos" "optouts" "recruiters" * feat: remove mongoose file * refactor: migrate types & services * feat: update create index jobs & remove mongodb legacy connector * fix: typecheck * fix: async iterable * fix: objectid import * fix: job processor db calls * fix: jobs export to pe * fix: sentry * fix: test * fix: job processor * fix: missing zod * fix: issues * fix: issues * fix: issues * feat: update ts and use mongodb objectid * fix: ui type never * fix: organization * feat: update mongoutils * feat: update eslint package * fix: eslint p1 * fix: eslint p2 * fix: eslint p3 * fix: updateSAVE * fix: yarn.lock * fix: sentry init * fix: sentry config * fix: job processor * fix: cron scheduler * feat: remove mongoose * fix: yarn.lock * fix: index script * fix(front): remove listener method * fix: etablissement creation operator * fix: formulaire creation * fix: correction émission de candidature vers offre lba * feat: update pentest mongodb uri * fix: suppression ajout event parasite * fix: script command * fix: missing 2dsphere indexes * fix: preview * fix: revert fix * fix: obfuscate script * fix: user update * fix: missing status * fix: job update * fix: updatedAt * fix: updates * fix: update etfa email * fix: update personal info * feat: update recette db uri * fix: appointment reply issue * fix: atomic operator updateMany * feat(lbac-2225): jobId as string * fix: aggregate * fix: remove address_detail * fix: merge aggretate to array --------- Co-authored-by: Rémy Auricoste Co-authored-by: Alan Le Ruyet --- .bin/scripts/seed-apply.sh | 4 +- .bin/scripts/seed-update.sh | 6 +- .bin/scripts/setup-local-env.sh | 2 +- .eslintrc.cjs | 3 +- .infra/files/scripts/seed.sh | 2 +- .infra/files/scripts/sync-index.sh | 2 +- .infra/vault/vault.yml | 1306 ++-- .talismanrc | 20 +- package.json | 30 +- server/.eslintrc.cjs | 1 + server/package.json | 9 +- server/src/commands.ts | 29 +- server/src/common/apis/FranceTravail.ts | 35 +- .../common/model/constants/appointments.ts | 12 - .../common/model/constants/etablissement.ts | 27 - .../src/common/model/constants/referrers.ts | 78 - server/src/common/model/index.ts | 125 - .../internalJobs => }/internalJobs.types.ts | 25 +- .../model/schema/_shared/mongoose-paginate.ts | 227 - .../anonymizedUsers/anonymizedUsers.schema.ts | 33 - .../anonymizedUsers/anonymizedUsers.types.ts | 7 - .../model/schema/apiCall/apiCall.schema.ts | 48 - .../model/schema/apiCall/apiCall.types.ts | 11 - .../anonymizedApplications.schema.ts | 62 - .../schema/application/applications.schema.ts | 144 - .../appointmentDetailed.schema.ts | 6 - .../schema/appointments/appointment.schema.ts | 168 - .../schema/credentials/credential.schema.ts | 43 - .../customEmailETFA/customEmailETFA.schema.ts | 21 - .../diplomesmetiers/diplomesmetiers.schema.ts | 43 - .../diplomesmetiers/diplomesmetiers.types.ts | 10 - .../domainesmetiers/domainesmetiers.schema.ts | 138 - .../domainesmetiers/domainesmetiers.types.ts | 36 - .../eligibleTrainingsForAppointment.schema.ts | 147 - ...leTrainingsForAppointmentHistory.schema.ts | 6 - .../emailBlacklist/emailBlacklist.schema.ts | 30 - .../etablissements/etablissement.schema.ts | 132 - .../etablissements/etablissement.types.ts | 3 - .../model/schema/ficheRomeV4/ficheRomeV4.ts | 24 - .../etablissement.formateur.sub.ts | 112 - .../etablissement.gestionnaire.sub.ts | 111 - .../etablissement.reference.sub.ts | 22 - .../formationCatalogue.schema.ts | 501 -- .../schema/formationCatalogue/mnaFormation.ts | 463 -- .../schema/geolocation/geolocation.schema.ts | 35 - .../schema/geolocation/geolocation.types.ts | 8 - .../model/schema/geopoint/geoPoint.schema.ts | 14 - .../internalJobs/internalJobs.schema.ts | 63 - .../common/model/schema/jobs/jobs.schema.ts | 166 - .../schema/lbaCompany/lbaCompany.schema.ts | 130 - .../lbaCompanyLegacy.schema.ts | 24 - .../schema/multiCompte/buildMongooseModel.ts | 11 - .../model/schema/multiCompte/cfa.schema.ts | 47 - .../schema/multiCompte/entreprise.schema.ts | 92 - .../multiCompte/roleManagement.schema.ts | 72 - .../multiCompte/userWithAccount.schema.ts | 84 - .../common/model/schema/opco/opco.schema.ts | 44 - .../common/model/schema/opco/opco.types.ts | 9 - .../model/schema/optout/optout.schema.ts | 81 - .../recruiter/anonymizedRecruiter.schema.ts | 21 - .../schema/recruiter/recruiter.schema.ts | 144 - .../recruteurLbaUpdateEvent.schema.ts | 33 - .../referentielOnisep.schema.ts | 29 - .../referentielOpco/referentielOpco.schema.ts | 32 - .../schema/referentielRome/referentielRome.ts | 46 - .../model/schema/session/session.schema.ts | 37 - .../siretDiffusibleStatusSchema.schema.ts | 35 - .../unsubscribedLbaCompany.schema.ts | 39 - .../unsubscribedOF/unsubscribeOF.schema.ts | 29 - .../common/model/schema/user/user.schema.ts | 52 - .../common/model/swaggerSchema/entreprise.ts | 107 - .../src/common/model/swaggerSchema/index.ts | 26 - .../src/common/model/swaggerSchema/offre.ts | 100 - .../common/model/swaggerSchema/utilisateur.ts | 62 - server/src/common/mongodb.ts | 44 - server/src/common/utils/mongodbUtils.ts | 222 + server/src/common/utils/sendTrackingEvent.ts | 17 +- ...18202702-user-recruiter-first-last-name.ts | 1 - ...-remove_is_anonymized_from_applications.ts | 1 - .../20231120000000-cleaning_applications.ts | 2 - .../20231127120528-remove-password.ts | 1 - .../20231129093200-remove-username.ts | 1 - .../20231129170900-clean-referentielopcos.ts | 6 +- ...11000000-trim-unsubscribed-lbacompanies.ts | 1 - ...27130954-remove-field-from-appointments.ts | 43 +- ...109100722-export-custom-email-from-etfa.ts | 32 +- ...ove-etablissement-campain-webhook-array.ts | 1 - ...2402270000000-remove-user-is-anonymized.ts | 2 - ...2404240000000-migrate-referentiel-romes.ts | 1 - ...0000-migrate-fix-missing-date-blacklist.ts | 2 - ...gibleTrainingsForAppointment.controller.ts | 13 +- .../admin/etablissement.controller.ts | 12 +- .../controllers/application.controller.ts | 15 +- .../appointmentRequest.controller.ts | 113 +- .../src/http/controllers/core.controller.ts | 28 +- .../controllers/etablissement.controller.ts | 74 +- .../etablissementRecruteur.controller.ts | 12 +- .../controllers/formationRegion.controller.ts | 2 - .../http/controllers/formations.controller.ts | 3 - .../src/http/controllers/jobs.controller.ts | 7 +- .../http/controllers/jobs.controller.v2.ts | 4 +- .../jobsEtFormations.controller.ts | 1 - .../src/http/controllers/login.controller.ts | 6 +- .../src/http/controllers/optout.controller.ts | 4 +- .../http/controllers/partners.controller.ts | 2 +- .../unsubscribeLbaCompany.controller.ts | 21 +- .../src/http/controllers/user.controller.ts | 44 +- server/src/http/sentry.ts | 70 +- .../anonymization/anonumizeAppointments.ts | 46 +- .../jobs/anonymization/anonymizeIndividual.ts | 188 +- .../anonymization/anonymizeOldApplications.ts | 44 +- .../anonymization/anonymizeUserRecruteurs.ts | 101 +- .../src/jobs/applications/fixApplications.ts | 13 +- server/src/jobs/crons_actions.ts | 11 +- .../jobs/database/fixDiffusibleCompanies.ts | 72 +- .../src/jobs/database/obfuscateCollections.ts | 163 +- server/src/jobs/database/recreateIndexes.ts | 15 + .../removeVersionKeyFromAllCollections.ts | 18 - server/src/jobs/database/schemaValidation.ts | 24 + .../src/jobs/database/temp/fixCollections.ts | 34 - .../jobs/database/temp/fixRDVACollections.ts | 26 - server/src/jobs/database/validateModels.ts | 129 - .../diplomesMetiers/updateDiplomesMetiers.ts | 14 +- .../domainesMetiers/updateDomainesMetiers.ts | 16 +- .../formationsCatalogue.ts | 7 +- ...rsupAndAffelnetInfoOnFormationCatalogue.ts | 17 +- server/src/jobs/job.actions.ts | 38 +- server/src/jobs/jobs.ts | 35 +- server/src/jobs/jobs_actions.ts | 11 +- .../jobs/lba_recruteur/api/createApiUser.ts | 22 +- .../jobs/lba_recruteur/api/disableApiUser.ts | 4 +- .../src/jobs/lba_recruteur/api/resetApiKey.ts | 7 +- .../formulaire/annuleFormulaire.ts | 18 +- .../formulaire/fixJobExpirationDate.ts | 10 +- .../lba_recruteur/formulaire/fixJobType.ts | 10 +- .../formulaire/fixRecruiterDataValidation.ts | 42 +- .../formulaire/misc/getOpcofromSiret.ts | 9 +- .../misc/removeIsDelegatedFromJobs.ts | 13 - .../formulaire/misc/repriseGeocoordinates.ts | 5 +- .../sendDelegationEmailWithSecuredToken.ts | 63 - ...dateAddressDetailOnRecruitersCollection.ts | 11 +- .../misc/updateMissingDelegationCount.ts | 9 +- .../formulaire/misc/updateMissingStartDate.ts | 7 +- .../formulaire/relanceFormulaire.ts | 15 +- .../opco/constructys/constructysImporter.ts | 6 +- .../opco/misc/correctAktoName.ts | 7 - .../opco/ocapiat/ocapiatImporter.ts | 8 +- .../jobs/lba_recruteur/opco/relanceOpco.ts | 33 +- .../optout/getAllEtablissements.ts | 14 +- .../jobs/lba_recruteur/seed/createOffre.ts | 130 +- .../user/misc/updateSiretInfosInError.ts | 25 +- server/src/jobs/lbb/lbaCompaniesUtils.ts | 19 +- server/src/jobs/lbb/updateGeoLocations.ts | 17 +- server/src/jobs/lbb/updateLbaCompanies.ts | 18 +- server/src/jobs/lbb/updateOpcoCompanies.ts | 7 +- server/src/jobs/lbb/updateSAVECompanies.ts | 33 +- server/src/jobs/migrations/migrations.ts | 8 +- .../jobs/partenaireExport/exportJobsToS3.ts | 4 +- .../partenaireExport/exportToFranceTravail.ts | 59 +- ...OnEtablissementAndUpdateReferrersOnETFA.ts | 28 +- server/src/jobs/rdv/anonymizeAppointments.ts | 6 +- server/src/jobs/rdv/anonymizeUsers.ts | 36 +- ...ingsForAppointmentsHistoryWithCatalogue.ts | 17 +- .../src/jobs/rdv/importReferentielOnisep.ts | 18 +- .../inviteEtablissementAffelnetToPremium.ts | 50 +- ...eEtablissementAffelnetToPremiumFollowUp.ts | 56 +- .../inviteEtablissementParcoursupToPremium.ts | 52 +- ...tablissementParcoursupToPremiumFollowUp.ts | 56 +- .../jobs/rdv/inviteEtablissementToOptOut.ts | 44 +- .../addLastActionDateToUserCollection.ts | 23 - .../addNewFieldToAppointmentCollection.ts | 6 +- .../jobs/rdv/oneTimeJob/fixDuplicateUsers.ts | 9 +- .../jobs/rdv/oneTimeJob/repriseEmailsRdv.ts | 62 - .../src/jobs/rdv/premiumActivatedReminder.ts | 28 +- server/src/jobs/rdv/premiumInviteOneShot.ts | 30 +- .../jobs/rdv/removeDuplicateEtablissements.ts | 45 +- server/src/jobs/rdv/syncEtablissementDates.ts | 75 +- .../rdv/syncEtablissementsAndFormations.ts | 118 +- ...cEtablissementsAndFormationsNextVersion.ts | 45 +- server/src/jobs/scriptWrapper.ts | 4 +- .../ficheMetierRomev4/ficheMetierRomev4.ts | 27 - .../seed/referentielRome/referentielRome.ts | 19 +- .../updateBrevoBlockedEmails.ts | 4 +- .../jobs/verifications/controlApplications.ts | 4 +- .../jobs/verifications/controlAppointments.ts | 4 +- server/src/main.ts | 5 +- server/src/security/accessTokenService.ts | 5 +- server/src/security/authenticationService.ts | 4 +- server/src/security/authorisationService.ts | 48 +- server/src/services/appLinks.service.ts | 2 +- server/src/services/application.service.ts | 167 +- server/src/services/appointment.service.ts | 86 +- server/src/services/catalogue.service.ts | 13 +- server/src/services/cfa.service.ts | 18 +- ...eligibleTrainingsForAppointment.service.ts | 42 +- server/src/services/etablissement.service.ts | 211 +- server/src/services/formation.service.ts | 45 +- server/src/services/formulaire.service.ts | 211 +- server/src/services/lbacompany.service.ts | 135 +- server/src/services/lbajob.service.ts | 24 +- server/src/services/login.service.ts | 11 +- server/src/services/metiers.service.ts | 10 +- server/src/services/opco.service.ts | 12 +- server/src/services/organization.service.ts | 37 +- server/src/services/referrers.service.ts | 16 + server/src/services/roleManagement.service.ts | 45 +- server/src/services/rome.service.ts | 14 +- server/src/services/sessions.service.ts | 21 +- server/src/services/trainingLinks.service.ts | 50 +- server/src/services/user.service.ts | 86 +- server/src/services/userRecruteur.service.ts | 106 +- .../src/services/userWithAccount.service.ts | 87 +- server/tests/integration/common/model.test.ts | 20 +- server/tests/integration/common/users.test.ts | 47 - .../http/formationRegionV1.test.ts | 8 +- .../integration/http/formationV1.test.ts | 5 +- .../http/healthcheckRoutes.test.ts | 11 +- .../integration/http/jobEtFormationV1.test.ts | 3 +- server/tests/integration/http/jobV1.test.ts | 3 +- .../integration/http/partnersRoutes.test.ts | 3 +- .../integration/http/rolesRoutes.test.ts | 3 +- .../http/romesFromCatalogue.test.ts | 3 +- server/tests/integration/http/version.test.ts | 5 +- server/tests/unit/formation.test.ts | 18 +- .../unit/security/accessTokenService.test.ts | 3 +- .../security/authorisationService.test.ts | 53 +- server/tests/utils/globalSetup.ts | 6 +- server/tests/utils/mongo.utils.ts | 30 +- server/tests/utils/user.utils.ts | 57 +- shared/constants/appointment.ts | 6 + shared/constants/referers.ts | 6 + .../generateOpenapi.test.ts.snap | 23 +- shared/models/anonymizedApplications.model.ts | 30 - shared/models/anonymizedUsers.model.ts | 14 - shared/models/apicalls.model.ts | 15 +- shared/models/applications.model.ts | 37 +- shared/models/appointments.model.ts | 20 +- shared/models/cfa.model.ts | 10 +- shared/models/common.ts | 21 +- shared/models/credentials.model.ts | 10 +- shared/models/customEmailETFA.model.ts | 10 +- ...iers.model.ts => diplomesMetiers.model.ts} | 56 +- shared/models/domainesMetiers.model.ts | 59 + shared/models/elligibleTraining.model.ts | 17 +- .../models/elligibleTrainingHistory.model.ts | 17 + shared/models/emailBlacklist.model.ts | 10 +- shared/models/entreprise.model.ts | 13 +- shared/models/etablissement.model.ts | 18 +- shared/models/formation.model.ts | 31 +- shared/models/geolocations.model.ts | 12 +- shared/models/index.ts | 13 +- shared/models/internalJob.model.ts | 13 + shared/models/job.model.ts | 8 +- shared/models/jobs.model.ts | 13 + shared/models/lbaCompany.model.ts | 32 +- shared/models/lbaCompanyLegacy.model.ts | 22 + shared/models/lbaItem.model.ts | 11 +- shared/models/models.ts | 78 + shared/models/opco.model.ts | 30 + shared/models/optout.model.ts | 10 +- shared/models/recruiter.model.ts | 17 +- .../models/recruteurLbaUpdateEvent.model.ts | 12 +- shared/models/referentielOnisep.model.ts | 10 +- shared/models/referentielOpco.model.ts | 13 +- shared/models/roleManagement.model.ts | 15 +- shared/models/rome.model.ts | 15 +- shared/models/session.model.ts | 15 +- shared/models/siretDiffusibleStatus.model.ts | 14 +- shared/models/unsubscribeOF.model.ts | 13 +- shared/models/unsubscribedLbaCompany.model.ts | 9 + shared/models/user.model.ts | 10 +- shared/models/userWithAccount.model.ts | 14 +- shared/package.json | 9 +- shared/routes/core.routes.ts | 8 +- shared/routes/index.ts | 4 +- shared/routes/metiers.routes.ts | 2 +- shared/routes/metiers.routes.v2.ts | 2 +- shared/routes/rome.routes.ts | 4 +- shared/routes/v1Jobs.routes.ts | 27 +- ui/context/UserContext.tsx | 2 +- ui/package.json | 4 +- ui/services/fetchFtJobDetails.ts | 11 +- ui/services/fetchLbaCompanyDetails.ts | 11 +- ui/services/fetchLbaJobDetails.ts | 12 +- vitest.workspace.ts | 12 +- yarn.lock | 5459 +++++++++-------- 286 files changed, 6839 insertions(+), 10604 deletions(-) delete mode 100644 server/src/common/model/constants/appointments.ts delete mode 100644 server/src/common/model/constants/etablissement.ts delete mode 100644 server/src/common/model/constants/referrers.ts delete mode 100644 server/src/common/model/index.ts rename server/src/common/model/{schema/internalJobs => }/internalJobs.types.ts (63%) delete mode 100644 server/src/common/model/schema/_shared/mongoose-paginate.ts delete mode 100644 server/src/common/model/schema/anonymizedUsers/anonymizedUsers.schema.ts delete mode 100644 server/src/common/model/schema/anonymizedUsers/anonymizedUsers.types.ts delete mode 100644 server/src/common/model/schema/apiCall/apiCall.schema.ts delete mode 100644 server/src/common/model/schema/apiCall/apiCall.types.ts delete mode 100644 server/src/common/model/schema/application/anonymizedApplications.schema.ts delete mode 100644 server/src/common/model/schema/application/applications.schema.ts delete mode 100644 server/src/common/model/schema/appointmentDetailed/appointmentDetailed.schema.ts delete mode 100644 server/src/common/model/schema/appointments/appointment.schema.ts delete mode 100644 server/src/common/model/schema/credentials/credential.schema.ts delete mode 100644 server/src/common/model/schema/customEmailETFA/customEmailETFA.schema.ts delete mode 100644 server/src/common/model/schema/diplomesmetiers/diplomesmetiers.schema.ts delete mode 100644 server/src/common/model/schema/diplomesmetiers/diplomesmetiers.types.ts delete mode 100644 server/src/common/model/schema/domainesmetiers/domainesmetiers.schema.ts delete mode 100644 server/src/common/model/schema/domainesmetiers/domainesmetiers.types.ts delete mode 100644 server/src/common/model/schema/eligibleTrainingsForAppointment/eligibleTrainingsForAppointment.schema.ts delete mode 100644 server/src/common/model/schema/eligibleTrainingsForAppointmentsHistory/eligibleTrainingsForAppointmentHistory.schema.ts delete mode 100644 server/src/common/model/schema/emailBlacklist/emailBlacklist.schema.ts delete mode 100644 server/src/common/model/schema/etablissements/etablissement.schema.ts delete mode 100644 server/src/common/model/schema/etablissements/etablissement.types.ts delete mode 100644 server/src/common/model/schema/ficheRomeV4/ficheRomeV4.ts delete mode 100644 server/src/common/model/schema/formationCatalogue/etablissement.formateur.sub.ts delete mode 100644 server/src/common/model/schema/formationCatalogue/etablissement.gestionnaire.sub.ts delete mode 100644 server/src/common/model/schema/formationCatalogue/etablissement.reference.sub.ts delete mode 100644 server/src/common/model/schema/formationCatalogue/formationCatalogue.schema.ts delete mode 100644 server/src/common/model/schema/formationCatalogue/mnaFormation.ts delete mode 100644 server/src/common/model/schema/geolocation/geolocation.schema.ts delete mode 100644 server/src/common/model/schema/geolocation/geolocation.types.ts delete mode 100644 server/src/common/model/schema/geopoint/geoPoint.schema.ts delete mode 100644 server/src/common/model/schema/internalJobs/internalJobs.schema.ts delete mode 100644 server/src/common/model/schema/jobs/jobs.schema.ts delete mode 100644 server/src/common/model/schema/lbaCompany/lbaCompany.schema.ts delete mode 100644 server/src/common/model/schema/lbaCompanylegacy/lbaCompanyLegacy.schema.ts delete mode 100644 server/src/common/model/schema/multiCompte/buildMongooseModel.ts delete mode 100644 server/src/common/model/schema/multiCompte/cfa.schema.ts delete mode 100644 server/src/common/model/schema/multiCompte/entreprise.schema.ts delete mode 100644 server/src/common/model/schema/multiCompte/roleManagement.schema.ts delete mode 100644 server/src/common/model/schema/multiCompte/userWithAccount.schema.ts delete mode 100644 server/src/common/model/schema/opco/opco.schema.ts delete mode 100644 server/src/common/model/schema/opco/opco.types.ts delete mode 100644 server/src/common/model/schema/optout/optout.schema.ts delete mode 100644 server/src/common/model/schema/recruiter/anonymizedRecruiter.schema.ts delete mode 100644 server/src/common/model/schema/recruiter/recruiter.schema.ts delete mode 100644 server/src/common/model/schema/recruteurLbaUpdateEvent/recruteurLbaUpdateEvent.schema.ts delete mode 100644 server/src/common/model/schema/referentielOnisep/referentielOnisep.schema.ts delete mode 100644 server/src/common/model/schema/referentielOpco/referentielOpco.schema.ts delete mode 100644 server/src/common/model/schema/referentielRome/referentielRome.ts delete mode 100644 server/src/common/model/schema/session/session.schema.ts delete mode 100644 server/src/common/model/schema/siretDiffusibleStatusSchema/siretDiffusibleStatusSchema.schema.ts delete mode 100644 server/src/common/model/schema/unsubscribedLbaCompany/unsubscribedLbaCompany.schema.ts delete mode 100644 server/src/common/model/schema/unsubscribedOF/unsubscribeOF.schema.ts delete mode 100644 server/src/common/model/schema/user/user.schema.ts delete mode 100644 server/src/common/model/swaggerSchema/entreprise.ts delete mode 100644 server/src/common/model/swaggerSchema/index.ts delete mode 100644 server/src/common/model/swaggerSchema/offre.ts delete mode 100644 server/src/common/model/swaggerSchema/utilisateur.ts delete mode 100644 server/src/common/mongodb.ts create mode 100644 server/src/common/utils/mongodbUtils.ts create mode 100644 server/src/jobs/database/recreateIndexes.ts delete mode 100644 server/src/jobs/database/removeVersionKeyFromAllCollections.ts create mode 100644 server/src/jobs/database/schemaValidation.ts delete mode 100644 server/src/jobs/database/temp/fixCollections.ts delete mode 100644 server/src/jobs/database/temp/fixRDVACollections.ts delete mode 100644 server/src/jobs/database/validateModels.ts delete mode 100644 server/src/jobs/lba_recruteur/formulaire/misc/removeIsDelegatedFromJobs.ts delete mode 100644 server/src/jobs/lba_recruteur/formulaire/misc/sendDelegationEmailWithSecuredToken.ts delete mode 100644 server/src/jobs/lba_recruteur/opco/misc/correctAktoName.ts delete mode 100644 server/src/jobs/rdv/oneTimeJob/addLastActionDateToUserCollection.ts delete mode 100644 server/src/jobs/rdv/oneTimeJob/repriseEmailsRdv.ts delete mode 100644 server/src/jobs/seed/ficheMetierRomev4/ficheMetierRomev4.ts create mode 100644 server/src/services/referrers.service.ts delete mode 100644 server/tests/integration/common/users.test.ts delete mode 100644 shared/models/anonymizedApplications.model.ts delete mode 100644 shared/models/anonymizedUsers.model.ts rename shared/models/{metiers.model.ts => diplomesMetiers.model.ts} (61%) create mode 100644 shared/models/domainesMetiers.model.ts create mode 100644 shared/models/elligibleTrainingHistory.model.ts create mode 100644 shared/models/internalJob.model.ts create mode 100644 shared/models/jobs.model.ts create mode 100644 shared/models/lbaCompanyLegacy.model.ts create mode 100644 shared/models/models.ts create mode 100644 shared/models/opco.model.ts diff --git a/.bin/scripts/seed-apply.sh b/.bin/scripts/seed-apply.sh index d2feb9adb7..64ab96207b 100755 --- a/.bin/scripts/seed-apply.sh +++ b/.bin/scripts/seed-apply.sh @@ -34,8 +34,8 @@ ansible-vault view --vault-password-file="$ROOT_DIR/.bin/scripts/get-vault-passw 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="labonnealternance.*" --uri="${TARGET_DB}" --drop --gzip +cat "$SEED_GZ" | /opt/app/tools/docker-compose.sh -f "$ROOT_DIR/docker-compose.yml" exec -iT mongodb mongorestore --archive --nsInclude="labonnealternance.*" --uri="${TARGET_DB}" --drop --gzip yarn build:dev yarn cli migrations:up -yarn cli mongodb:indexes:create +yarn cli recreate:indexes diff --git a/.bin/scripts/seed-update.sh b/.bin/scripts/seed-update.sh index 07d59775d5..4e39256e03 100755 --- a/.bin/scripts/seed-update.sh +++ b/.bin/scripts/seed-update.sh @@ -32,13 +32,13 @@ 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 +/opt/app/tools/docker-compose.sh -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 mongodb:indexes:create +yarn cli recreate:indexes -docker compose -f "$ROOT_DIR/docker-compose.yml" exec -it mongodb mongodump --uri "$TARGET_DB" --gzip --archive > "$SEED_GZ" +/opt/app/tools/docker-compose.sh -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 9720808e25..93964571cf 100755 --- a/.bin/scripts/setup-local-env.sh +++ b/.bin/scripts/setup-local-env.sh @@ -47,4 +47,4 @@ yarn services:start yarn setup:mongodb yarn build:dev yarn cli migrations:up -yarn cli mongodb:indexes:create +yarn cli recreate:indexes diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 1bf514bfd0..59d8321703 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -20,12 +20,11 @@ module.exports = { ignoreRestSiblings: true, }, ], - - // imports "import/extensions": [ "error", "ignorePackages", { + "": "never", js: "never", jsx: "never", ts: "never", diff --git a/.infra/files/scripts/seed.sh b/.infra/files/scripts/seed.sh index a633cc3c58..1b5d0e27bc 100755 --- a/.infra/files/scripts/seed.sh +++ b/.infra/files/scripts/seed.sh @@ -20,4 +20,4 @@ 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="labonnealternance.*" --nsTo="$TARGET_DB.*" --drop --gzip "mongodb://__system:{{vault.MONGODB_KEYFILE}}@localhost:27017/?authSource=local&directConnection=true" +cat "$SEED_ARCHIVE" | /opt/app/tools/docker-compose.sh -f "/opt/app/docker-compose.preview-system.yml" exec -iT mongodb mongorestore --archive --nsFrom="labonnealternance.*" --nsTo="$TARGET_DB.*" --drop --gzip "mongodb://__system:{{vault.MONGODB_KEYFILE}}@localhost:27017/?authSource=local&directConnection=true" diff --git a/.infra/files/scripts/sync-index.sh b/.infra/files/scripts/sync-index.sh index 02946a7619..b191fef3a7 100755 --- a/.infra/files/scripts/sync-index.sh +++ b/.infra/files/scripts/sync-index.sh @@ -4,7 +4,7 @@ set -euo pipefail sync_indexes(){ echo "Creation des indexes MongoDB" - docker compose run --rm --no-deps server yarn cli mongodb:indexes:create --queued + /opt/app/tools/docker-compose.sh run --rm --no-deps server yarn cli recreate:indexes --queued } sync_indexes diff --git a/.infra/vault/vault.yml b/.infra/vault/vault.yml index 21bd51eb56..f8b367df18 100644 --- a/.infra/vault/vault.yml +++ b/.infra/vault/vault.yml @@ -1,654 +1,654 @@ $ANSIBLE_VAULT;1.1;AES256 -61313735376632633763323739306136313433623632353039333832626338666632323365303362 -3530643330316235636634306138393930646466383962370a313031393734633235396132396164 -30303233356165616266356563336463393332616662616162393563303061343139326137353639 -6439313736653239360a316539316437333535643263343335363530623466373032636365383438 -64643035323063386236303261613031623964616234356338323834373864313237613030346464 -32363062353533336439613366376438333134356362336632613863363036333766396166666133 -65333539306661613234303239376236636339363938623936396530383763656432386332623963 -65313966633336623133336432396662356366303234336139366239653234666238316230353333 -30633664363966303330343061376432633935636534323135633433643638646531326238373735 -61343830616134666466396135343761383536316338633564373466313463626134633238316539 -34653038646234373838613539646635343963356362353330373265326135613863643363633866 -63343937346536383330393930326233343233393430383664363636636335343233383331636361 -33633865323635306432356663643866623161363264336661613135323930323339366361663762 -36353835353164653232336238386231313332643635303835636231626331633534326464353937 -30366466383561346665306531643537313836663134376663646530313238326566393733656337 -35643138306332626433366262653264386564623563373662613134373130333331383231363030 -63643562656265373438303561346465633131656461313338636336316566363736653739353335 -39623861383866366335316533333631656365663530373366313734613231656138363762623865 -33323135363731653534616562376263626365333837616639353865363063633435663230326237 -64373330326633636139383062383539666565346566643566386563623762343939346231383839 -32613466316135313038633639383430393561656330326532663463353065633930646339343462 -65666435306364366235303163653865333964346263633563666361636161643765376335366630 -33623363353837623039353133353365666461316534356364346566653362303866383038386534 -30633731313462303964323837623537653965373661316465323266616438316231613836636564 -32396437656366333566336662386430663738636334336131643865366134663031666365313936 -30343865386536653236666539623330386631343236626265353338343264326435343230303532 -30326232376632613837653430656638303861366336386439333533346138353939336133333461 -38333339316531343830326338326362656232386234626136376363376131613332343331326137 -65643333336565303138626532636231616131666164646262396631656161326133373632363738 -38303461623166356531353733343363353261613861373339633030636236373537353763316336 -63653035393063623462633662633638386133613335636662653565303839613332363933626363 -36366135386165333166373139323265363633323930616338326363616434333066383636636431 -34386466643831636135623933323937303335373337643833363862633964303933626537393466 -65326335393433633535656430663733313466313331663561346139373730353065303638633938 -30336137646266353833306430383166653366323536613439653039613233636262663232623030 -37393264633266323937313733313433393165633561633733383739353932363136663031646337 -30653533373230383062373238313839353361376162316435656663656361306535653330346564 -37633936653831373566363731646437303230343133653563346562666265343637613139653831 -64653364333364656562626166653666353139636130356465316538393135303535616331633132 -63343733653031316535336232643463303165333135616538303732666232666435323163343966 -63353136393039633566363338366130396133323939636634363665633330333930363663626632 -33623331643730336464636165303063343566616132373235616130333632393638646665616565 -37613761643539383037373232663638643662343736323635643635336536346161303464646466 -66306461333865386161343230393663333435393533623037306132363237663063353236613832 -63326366643435313164313130383863363330356630663937313937663161623938616163656335 -30343933636262393230623637666663656236663434653464373563666635383639343130353338 -61623330313336303530396666353635326237316138663930643539653839663131376239366337 -63306332383630353737303062386536333332646135343434633961616438383837363364626138 -35653539303434363761336631616666316335333634343864636336336138376236623235626261 -35313534643765653038613864616536663434633635653135626135353264636665383261346638 -39623763313665343566386466343133313766633564313566363362336330626630656136323033 -66653639663839326133343966366137653735353134336366316337336262633063386536343132 -61336132623536363065313830363361313231383037653532343562396334653639386437373232 -36313735366663353762623933613935386634353339666663306562636264636439393330646334 -64643639306566356366333361386363303832326137336137373234343637656539343236633236 -65353834303135623137366164643961643036623364626336363433306536613861306337346434 -37373735653066326331313933393733633865626636633137643339636165356232333162643862 -37623636633733366565373539343438346263666233313164646232383466343862333538343732 -61663933393739333331653733356531346232393932336163376533613963616666653831336430 -39353833653261643333376133643239313938663234656637626438326437306562313134643837 -64653230663965613064613233613939303934306562333136393037313639396462646234613032 -37323163656432633134623861636665373337636430613232303061393339313039353431346161 -30633939633666613831376361646137653436373635616133363563636265393336363365326461 -33313632323932343136383564643863316331326239616635663164633639373733323736613035 -30373631303263336638393361616339616230313037323639343836613930393231363562613466 -63363463656266626531386634333062366132373732323965306338343734373335353635303932 -33343365613235653432363833613131343734373066643666323664333862663035373633653436 -64336436323236393333613063666137616366623932326639326230636662333731626536373563 -34656162366432313837353134366539643262653463316139633639643762376132343932373134 -61363562363361323738383033343230346130316433306535613739386238646437623434303234 -35623766356239333438656430653133336635666162353532323562376264663530613633326135 -32356338636561653535663862643261343065643262326232303434306666613032383939663062 -66373763323534333163653837333563303066383834353732306438636665613838336538666439 -63616331303636396139373238363731303862393262643734646338346261666165616266313564 -63353734323936306634366537656462613532656534366565366436303062306532623232336333 -65343765646666316161363233323265333833636266616531393165623137393361626533356137 -35376530303631663834656333373464386562346265643162666236373238373436343364623564 -66366136383736663039633736353531613334643363663535353939636361383437323136646663 -66646538616566353465316434373761633233636463333263336465346436306164623133366137 -32653435633433363338323634623536616230653334386335636361326532613032626137363534 -66303561363963333265633164326636393161666265353337336661313630363530636265393332 -61316238626439626439653839613639373364613332663730316631366335313332383235363031 -65643161333164323464653366656534333539623362336331656662343832336330383864366436 -33616637326163643136623537323538636433336438336231613533666563663536333565383031 -36643232356436356565613562303461396562653936653239303738343162636439353832393737 -37653035376632313938363930653139666463666164613338353862613537346666383639393366 -35323934626461333837303265316365333766636138643737353135366138663264313635613830 -35663239386234663138646433623133633366663263316565653563616232313932333666343965 -35323366356331313864376664313565303162643839633865636333633637626330343637333136 -39356465326665633033386661373862633836636162373239653939616364613236393164336338 -39616239656461663462353632633235383566303463333738663532363462656264323039613335 -62336664353362613864313462653061376564313163303439356130313061326363636530613038 -36396533613038316665663639393539306132643338303332396165303664393733653661646432 -34353763643936343064323938643430363462383333653961613833373031663836616437306462 -37666237613631396165396264326564633534396336393363666430356330626431313663656539 -33306535353966613139626135393431383539666437373664323032623234373933663130396465 -37613933663330353639346437333937383063623634663830666535363035663266613438623833 -38396430393138623964613936616539316339376365653664613666343562626132336136623936 -39643434396264663935323961386465366631643936616237383339663435643861323134363263 -32386435323830623534306235653465336536343165663937313661613235363262346164656434 -39363933303335613438326439323463326161636165656666633362633834616632666631326130 -30313635663538313262303361623432396466623761633930386634616561363333313761363866 -39393961663639333563303535363933656132396434333066336332636464613037616234323234 -65613263333264316661643761393130346637316366306663323432613133633230376164663532 -61306334616637393132613636643637343863636536616266653230353761333936363133663362 -30313334653739626131636632313630303037313335343965326366633136393438633564396264 -31633362333033376164343633646135316633386532623039366562303764633062643230653132 -38373333323361666663383034323131643766313538646563393039663336353836346665663965 -30356431383532303438343939633938663137323163633561613835616134386639353234326332 -65343035663434323932636361613762396636376561393936643633353961373135356336376430 -35613861393666373938663165616139393239316431623237656232646264656233646335313965 -35343363343961643530303761613330313432386331393639353165313361336434633761396535 -31313861653539306533346430663165353561626537323362376538633163383338316464353331 -33383965643161346235316564396439666134653032613732323833393433313561666664373462 -62646565656662363030343631313361366464633565363132383438306262323137636434373835 -32636638643930396631363866643337373862663062326663633664616663633361386230383536 -65623530366530653964616136653638616262653563366431623063373938616138666134376136 -38626663643536303132653936386337316239666663376134643932636161623634326461363839 -39616537633539393162633462326265333936396364653661306561376536383166386534663431 -39306662303162316335653533393734303865626366613231643761303132633336623637393663 -32303466643462383530663665653062353239636637623566653365343862343964623535313363 -62336437316562623332633533666663313466303337353131636230353865366134313265326334 -37396463306537646535396463323135313836643536663939323435313738623433333437633036 -32303366343433313033336565383032663638323335383764633631613030653166643537356137 -62306163386130386463346462373830383962303733336637373666393762383637313431343465 -64346431626231303565653136366634383861396164326161623331633739383036356665373261 -33616635653232663732643732343334326162386438613132323931316336323565336365636332 -33323835373465366335643963613565303564336364646637663339313064613739303865396332 -34656363313866316365333862653966323732633635383038376137653731303761613131303966 -30623439393633333963356236343062363464356437623536333566623565323733383437383836 -39623636643735663265656634663639306133633336346666666332363762373066326331653966 -62393664303136333263633430333964323164313838653830643562636561313462356566633037 -30376564616539336363663061653734633166373034653066356630663730323833633562366336 -36613534643163636430623832646535653638323231343463656565336135633730636331363233 -31663562356137636565356639343631633464663731643665376465383332653364356333643336 -34666662373330633465373134333763393166666262313839646639396132343264316266396435 -32323535336635346363393263363033343634656536666465313062333630353736666234636233 -30383937613931333265386365616534303962346234653235373162643335316265646636353561 -62616565623037646631346461303538636664656564343235326164376138313066323831316330 -37626365633337623163346238613461303466623565386430653637373864373966666363666364 -62653162393138383237646634336639663963346564656132376432363862666331356265353566 -30623635326566323833353761366630643464616236663233636330633232303166613362396435 -31363136393036613739303762343934626137643337383062313564653930633166396435633136 -39336561306235393531356133633663323638363663613866396465633964656663383139386137 -63323966333465643161313636326231313530616166613064336232373264656333656164386439 -38353137316131653233333136643834633766316264333234383636373134306238363931366364 -30656466373063313132363761356138363865383463303264346466393639303533633733663733 -66363366336330386634653962313134306132616433313530396137613332353239383137636231 -32653331326263393534643265393535643666343135656162643366366131616339306232643036 -35343037646435363637333039613562633438396361633764613130343036313963666665393334 -33353432663764323162653562316662393731343439663336613662303133646633396637383761 -66393362616539613266666134353632363163363238353031393734396333646435663736366538 -63326233653862383139356435356636393134626161623266316232623535306331376432396134 -31636235613466623466666435376232353661643766396634306232386630363034663364626364 -33666264626165383038653334303631666537386566623238613739333432356335343032393939 -37643862613237343962376264356338383966663861386665336562636139633131393736393762 -62623264326135323538363066353064386630386535656137333535626339633233333465643961 -38623532346263633030656235393836336363643234353839656233313738396337633134383334 -35316637623731306363343931323766396435643762613937383564613664383861313766353438 -37353366633163396532313538356462346136313735613739313966663132633830393963356461 -66323738663935336633343130336361313936353930343365303164373935336262623731656261 -33383563613264656635363561376665373763343361373838383866646135343766623330316139 -36383334356564656537323438396636323563663930623236366262383665306562333131376638 -39623732336364346232626461313163636662643836373637616136333630323161393938376663 -37663963616236303666343839613364353064333964386561336462396364626233616139366534 -34313164303637656536646662643836633764653063363430333134613839326262626165623461 -37643438636130393636343831313861373965373565623166393762376663366233636331616232 -64323737653336386430393338323265373130653632666164373165396635356463636134303337 -66373932383632306338383237363938616261356538376633386332616534343335316135353863 -63623137393132663364653863366162666361303438623333386466656333303739633738613666 -34383961313932376630613565346664633634623831333261326434313130363366343163626362 -32666564643538333932316634386563653764613637333265653930336333656564663738616564 -64326134376634616664336137643530653134376431366239323035393932616438616433373836 -32333032373038363766386364306561353834366635363238666466373965633431643864306639 -34346436643065343839343833333834313330633837353565333530303136633036333765633230 -62343466303762623932373134663633396138643464666331653432636535396664616237653934 -33366634376663363134383539303939333530333765313039393862343035373965646366633635 -38306130356663653262343538323039336464626331316235393266386632613138373166303534 -34353838316234663166373066306364363836613061323531313232303061303731646635613235 -39393837316264343332633366643634343164386162366336616262336162666535663066393464 -61653436383930626632356262373735373338313834386133623235376538643030353936373238 -62303232356139333963393566323338336635353363613865373439346139383335303932633762 -38356463306135356130393063373337386337616261363134663437666234333339333333356634 -37373531306432626562363364303962626632333234616636343837363131333564316334336664 -65343034326234313939306435336461623237336335363138383138323533636638356163633237 -33633736326439666237636166363338616165363262396230333938666263373035396331663865 -61666537376630613636333361656266336363313538373561353833373866343436383239316662 -30666139393435643434626435613866636630653761363133383861393734626263643937313036 -36333362323835333432656636653765333032396264343837363033393439323232333866646330 -63326630383038373236626165626661333261353333333564393135626666303630653363333966 -30363131313733303232376636373037343537393964393061303266396532646531616539363739 -66643933346664623061303936393232353536306336383135333563336662396433643534396638 -30386530303431616537306334303737353264363862636561663762376431386566343265313839 -37353765313539666133336663343262313839646536633630623039623633643833663831643466 -36653334656462336533393166333137333661353838313263393935643934623364623635346165 -66343361326662663662663935393265656632313362366638366332636563336632633231343535 -63336135343932616365626531663532306637303166353632353334313930333364303735666439 -34643563303731393239666638633966376632643134393832656631623865643433383435306561 -61633563393062353836303666663139646231346133343836623664656332333066306231333637 -31313934353630633765303063643263623438663166396461653034616437656436663636663033 -63343336343833323835623135336262366332313338313262633765656134333636643030363766 -39363161613936643630393362636335306431363064383731623239316438386439333865386562 -63616463373332373134656465326339353335613831333931653665666439316339666661636238 -30623934346635396630653261616666376662323333626437326537633033633833646665393861 -61636365313065396364343539393061613636363036643932306363636539356662363833396234 -31643633373261323835336538386639343262336461396136343933356266393339656435363330 -34626332326435366537303933333162396661323566393138636339646333623933303664636130 -63656666616161393138333161316365653830626432323265636430336464653531366137383165 -62306336306130353863616534623237316235363530373431303039373464316266346361383466 -33373365303466653639333831663533333466646438616134616630666263356563393237656461 -63613865316166356436656135323063623735393263363365653265616366663363353466343266 -35633263363831336632393665643630616134393839383962666333616664666137646630616430 -63643135636132666233353633613336653130316664373633613637313034323232396266306666 -31613031633466366633306665616363396137626166336633376230623665323131336430396631 -64383236326634333730666139666239346466643034306464363431333766646562376231663561 -65333933356134323734636534396464363938326535373136386338313865626136623235653436 -62323438633235353361313834333234363561363662633966356638616237353334343830333262 -36356532636661346538303632366230663639653331336232366437376536313264326562336435 -64366430356333393763383939316332366466333162363535356135353864343361366232323536 -36646265376137623538326665313936633161663431383239306438663061373463343232306562 -34653665316530666562336536616237343937333430323332633831396235363336316637353338 -63383432343134336462306262663364643437393562346366316636663838323537363631313732 -31613539383535663437313964633163373631613939303464653164373839653161323163336232 -39323139616162653438663138666338386231623338613562653366623433373130383661656464 -38663866373731633136386662303638363336346165393133356664393661613761386264373363 -35366137313032323334303031646233643532613133363230306636366165646135633532326366 -62346136393033393665626339663861666437356638383130623535343531386232326537353532 -36383835363530613735643332613337666135393333316636613964666436643564616636346239 -65336464653664653064633638386263613734343436643832663131663638613566336166343330 -61633931653333323730383133316533303933383738666266386434636234663732303735366162 -62326536306430373332333737333631343735396634356530393431373732363231656437333930 -66366166393032353566656335373837323134636631636162326430613338393238383734346233 -63373436653161316361313533336233666536303739346339376234663038663261383133346663 -65343234366163383630356663313665343761383336383137636131633534643235326139653630 -61336266306664396237643464323261653062356432336233396665326530346465646464623663 -38646463313032643566343139376233653862316330643738303762616562653032633961373364 -62643136363633323934373638396363303464326437343466393435393935323263643330373637 -30326135656635363435366533366637636235346266643130363939303037346164623863313161 -36356466303039373763306665383561613431333761616265336135333832646132613064323239 -38663135653532363130373963616338643962633631656135336363376364333133313633396634 -36326630396437356336376530616237363830356430643035393735633336366466656633353866 -65306232656561396466393837633361376338306636633062643235393738316339663838323439 -37363133343634643335636438653337363561623761373839383336366239333335636130306338 -36323362333363616131663439636236303830336639646535306465643539303764346337306432 -63663266386338306131306538376237373336366165653431313935653734636561396432373137 -31306466333531393931666634636563626561306438656262396162393837616437376433396162 -64643066633131346234306236666433306132356638643437623636323765666635313063393535 -35633462376564346166633831363638303435393166366231366534613237366663623165393539 -38303264373566393936643632663933326166356334316439326333643031633239613764623031 -38633235616163333939633633373437346430303963616565313534626361623463306165373234 -37343235386437623061306433356638323064333165363438386532343130303865656239353236 -38656636303362663963366139623461666265303138636565393037306230303931636434613463 -38323763363130643939336166353231643161303961633339366631356336646536343565643262 -31393361353533616461353437353738393632346639623163616339313831306431303561653634 -36623333646636613066386366623535323735313862393463623636356462316639383364613636 -33373163376337393564343935323063636538303138383765393339303232383939313566313431 -31386165366237333766323062366461373239613565613662333662313231373531623935376364 -65346563356361316538343566633234303236366238616131356434393838623831326166646132 -62373562376139373961366665336138666162646239373333613838383664396161636339306362 -32393331303933343735383663333862383637663262653736643236636338386335363663353337 -61396138623336343863396463396632653130323234393034386161333339656137356631626334 -38323932376133346533613066373065323663393039646466653435383061656635643636306337 -37633732636364613533663439323039666535643138393262663461396161653264656462313366 -32343138383639656566363862343834636534316364643833353437653262353266653930393634 -61356339643035616366303262366465343661343536653866366430653131383336636431336362 -66633533626638326435393438653161386539376233353832653336663531336533353230376638 -32386630633264343337643430313236613936623934373437613935323937633134663937666535 -34386164396663393932663536353032306163396135396666376664646432666230366332643963 -30333435643830353433313666333735376666333066626230663339663663633739623630343032 -62356333643261396231633534663538303763643561333639666434383065393261636634646261 -33666432313339303232346334623161343337376531343262376435336466376439666639373738 -33333761336634393436653965636233363166623065393166323262373239363231386235636231 -38376564303532666165343235653966343337303938333761626663303433613530366138663235 -63393062386630336364323666636433666363643934356135646364643636326437386231316562 -39363165643336663635613831376163373261643337383631366665623239666564633363336437 -36373863633037393838626331323465353163323336333738316238613031353334653135333933 -31323666353865343830303936653035663365356534356230316366303239346162663537626638 -34323132343435356365366165353966323039643365313661626637663236666438373666313432 -33613831653937376334303539616336643561376462383863323831336237323532393665323937 -37326335356466646161666430303066636233653863613738633039353131656166383231303762 -33323464626635623962326432333561346230633164333737396635386234333338373439646664 -62656165313465646330323036386132383638636165376334383261323337653430323266626632 -33366165383235323131323331623463336534613835393831336463376232653431353965323664 -65356234633834343833343432393135623535656336626533396136366363643564646363383534 -62653865613338303236313438613932306263653034643837363630326365626531363635663737 -65373735366465666464346134373032616539633535363666333436346136346537613565336531 -66396335653739346565333466376366316636386261636262306432306230643832313138363061 -35616131366438323534623430616163393930613364306264643230636365646337376435386262 -35366237666132636134623538383366336165303934633064393162393438616164353862646464 -39656664653966643431636337326466636261383539643465393534346163656634323839393161 -38636334663734666230333437636461316535643130613538323338386564646336356465623066 -62343439646337306231383732393063623334313434376466616264613933373264353933303262 -33373265656162383934666263663366383837613434363165383761643830316232346262306431 -38316533626162363136623234306531613061363461333039313661356230623861333261333865 -35663766396466316362666531386361666661313135376439366338346463363239343730633735 -64323037393938366235303633303935343837613565333632386337616262366132616434333963 -65653935306634323361306531666566343530363435323437626337373935373431386531376137 -66346432306464613761373738643438353062306138313033613831383337626434643165363937 -65663337306231343135623038383035666432366330303664316534643837616530663139313030 -35383834363063363630306434656137346136343865626633396537306661323139373662363363 -37663262633132373961646363356235393937363837383436393362383831383537343462643564 -36373466363932646233326532626561326433663736326337663030333838333535383537663465 -39653235313130373730613936383738636166653966383763383237653431646666316466656265 -32643663323065393831323765636139346536393962383330323066386362303731343764386639 -33653432313366326465666632383532313362643236633636353738653134653937313530326130 -32376162663166636138333666336336663865323463623137373330356664383939313836313731 -34313731353065356635623730666539333762643033303132323461336135643066626232393966 -37303930613064343034653837646566323838323864636263366163366631376263376430356339 -65626262383536646238633235323734333538383161353265396132386564386564346636396436 -32323237333137393738373466613639396330386231366564366638326435666536643635363930 -32663164646665633038363130653135303962663335633033303230303166313666663262656261 -64313262306337663463643735373935633332636461646232656332326462663930323938656331 -38666531353439656335643034373663303464396237383236366463653438366638316538623232 -30613333316231393130323262353266326537613365353765366634616464313130333966366534 -61633135346531343664656437313833343332383063633332323961643332333530623533353837 -62656435386534613238613835336135613832613930356362396239303965666138626438626530 -35393133376633653437363462623765353931333463373464366663666139383436386465393032 -33633664623431643638346431303461366266333561323730323738396164393333386261313663 -38346635363462333436383031343162336137396138303635343666613532643263333234353261 -38633166646562616535353364636331376532363731646136646631646165393935313261393431 -33653339636536333337616632353131363236356239623663323934323565373637323965333433 -39353833616664393836646130353335616563393764313535623734376435653338313630626164 -33313939386539653336663339343065363030363336643930363565396439656339316239616530 -37643464626439633566396661363161303035303835333234313364646561396633303732393861 -37303833623462353937663635313236333264623933313462623161346665626262316534363439 -62353863633434656235383162373234653961633135666263346565383532653961336337333638 -65613530613232666163636338373362653533393231383538626237373635616266343865323036 -38336562393661666264613663366162653632383866653331653331653830373737343764396161 -33353536303633643230613163393738306331396437316338323534356638663537616531326266 -63626166383665636530343363656662316537313831386336313461373334663061616330636637 -33646434363861616537346331663931363432366661663732333934363734613739653530373665 -66386466356139363035653561666239656464353832373261653334633635633762343730336437 -65316233383863666331323931363735386536356466666432343030646664303532313839363733 -32323364363865326163313564616363636231313735343065363962646634376530653765306232 -66303232336534643031636435353666333634363566336130326166346535613933373030333762 -63393266643639393634393237626661343035306332393561613762663538313864386231396135 -32613332323262613935663938326431663430613233353463613735316139366666656234656535 -65663566363933623664613236633637326637333839363731353435636562633130346132326436 -36336336306233393331376564623331346662656239376133393633623634666537383737383438 -30613534356366663838663464386538636439636536383838623936653263653262323836663833 -65383030343761376436303261636438376239343862393938643765633539303134383536633531 -39643938366261353033333265346137373936323863396132343230326436393737313334363762 -32623963623130663462313834616336346537656632663636616665393963326262353064363539 -33323231343831383261623664373233353565396333653538616561373939343664313365333738 -37636133376238353637313230353737616437373836376265396432333935616539336363633533 -31353633376534393264366635366133306339353564663165363433636336333530306665366633 -39323439313231336331656663346138353131373662343639656362383661386266656237363730 -63363339306661303065316533623035396639333461656234626164353431356661306362376238 -33303363326662636563636235383637353365626336326266303337646637336166326638623261 -62613931386333376631383264363537393139653731633266666336326439343834333934343730 -39636261636464333231343531353431306262623536393731393130306539356139633230373861 -31363931346339386234623034666264633563363061313165373135353234313831643762333261 -35643836366132306231663431396161363431353164396139333966313865386333353730303961 -61303737363936633564623663346264623263336566343030316636316666666537396463646432 -61393730313131373234323961373664373132373233663932623638346337323737653636666335 -61383462353032656464383237303032376139316635363037333062396438626437643132323837 -63653361646536643762653836333564633236623531373262613035396333613133653536346561 -31626261313736633738643330643863383835323530383936663238633934306339356638643365 -66396533376463646338313438336366353763336464643961636632356635366165653132643833 -65323833646561623033353162376334656530333962383438343863636330343031343336653135 -32626338393564363637383130616665316266306365643132613266336532633366323139353638 -30643332663562646566653761666439323634636465396231343339333633383334643365646231 -34316131393033653233346236393339643761316633313933373433643665653536373565333564 -37666361333766653337366235386664333063333665343733323135336265656537353263336133 -36383762363533623161366434313065316566623631623236313935316530653231623264656461 -32633238356430653464653738623436383731636136393331653265363837623866343337623231 -61343835346365346164333166653330316665626463633661306262343438363331356632313564 -36396563653236393133633565646636306639636539333030663662306463613761303531386162 -64613262393865393234303238396263333532323935373136356332666466356661653865626436 -63383461393635316331353734386666373261346463636363393036383732303661346664633461 -65623234373130386135633033643032623135653764343435306634363564353530323161326531 -61313532393634616563303563353863643732633130653735663138636466613863633062323336 -35316532646639626131666536316631306138393635623537643366636561343663663632393238 -61346130343937333465663037353834363161313039316136346635346339336563363865633165 -61653231636432646534336435386466376436363436316337646633306134663333336333663765 -61666236383764643661613061666562346134353761343063303564303236366266336664613666 -36346237353830303561323534383939343537303630343730653731363332313832376132313463 -64386631663135623034333632663364333239666234643837636463306235386561346234303531 -31663163613036613431663536656135643263623233333436623738633636646335333561663430 -38623636333334656262623936653466316562393633653935613031316636656266353966653463 -34663237623233373234326538333239376536633763616639383734373136303739303533643333 -30343962303632623934303638343635643433393033643835623932373936333839356564633632 -63346437666561323130376362626635663630356664633565666566363062616363623361316337 -32363263376166353362383766366435663964336333643339663832666662643566623564343139 -62356335383865643261383930616634613465343039353839393634626532643138363432646163 -64643539316366346132303266323534326335373965666266306461353665323932316135313434 -39626136333438363333623864646663326230636639383532373464626264353439346537363163 -64623661633166313962633163353739333936333433333665333637303933643738386334363866 -36623231646130356462313631393136333839373530333631303766653762613737373666306231 -34393561666261633431366265373265386237393232626634613239653131616365616431633263 -66633034386335633330616231646237376166353838613266346662373233623838353364303731 -66323032663138393763306261653066643332326437613037353134356237643166313332623362 -34666635316665663166393736666662646639313864343766313632303066613365336238383237 -38383636633636376165656538366366386236313566343164316132653831383961373531333332 -38626361343461343133306530326633376565343131646532383530646561613239616439333465 -65663231343263666236343535393166666630343363326130613139333965653735646131656337 -31393132336133313638646466613363323262656664363839646536393135393365613632306337 -31333564346334366537326363313464366636333939633532326262346362643862376633306364 -39663735353839663265656134646566646563363238346334643733323538303762333130343462 -33373463383636313661376364383334353066656162383362653762636437386135333066376438 -62626265383432336435303330333337636538363164373533333431636465336238333733346633 -63613138663536333635656230313235613032343263646662313963616265636434323335633462 -62326138633266616237633465653334356537633332376164636439323434396639313736316266 -39373239363633333561336364353531326337636236396130326363633630373835323361633736 -65313762346130373736316265363237643231376137656566353765616138663463316436353035 -34346534303536316362386566306565333633393336646637623333643136343961623030346161 -65313936663562663536313239333539643837323638323630333233396236623739346136313766 -62663136376466383666306466626532626632376537656536653536643530323466333135636137 -64333636663332376661376565383037363634303865346562646335373065386265313634636465 -66333932356532646666343264633332363662376131366365366539623761343263396535353666 -63333266343861643731666532653538653138353064386237633661643163336461616265323830 -31326666636230633637643830663464663835386161313035366531633838306336393135666464 -32376133623631666630373863616631613635343938333435333264356139643636636639323462 -66346237643261323034306633343737323734376265336131626363333233393161323533333232 -63386530373062613837343134366561613036393161306138343931346335663564383165633731 -38343138616633373932633666346565366332386562393663303262383366363761306364363936 -62323966353866666264353462336234313465356534393633666138623261336232336536356164 -35373361376165373563626239663465316238666232393936393261343436353337393536333932 -38656636393366303230386630663834336538613766663738343938393230333063313765633464 -65396533623831383662623966316561663163636364643463343134313233356333653966623766 -39343334636265303538306364323033383433313131386635313666313161333630636430613964 -34313763613236303731626537333764313865313635303838346538333633623363646666363836 -62303164343363323333316261626361313735333138646438313764323233623261343763396232 -36376234343339656430643234313062613731386136346530373938326436666361663534626532 -63663562663137393862363334393764646562303034323461346437306564623635356138626565 -62623163306537636665326235366463656665613134336439353738356432353939363237353764 -30356462383236613031313565623166383138613832396365396561656531633732346635666633 -37623235306533303633616234373136626533313664363736353835386264656538333362343835 -31666462323738343636633830393163643839323465646564356432383864323630613964333538 -37613132623639303565396532343562336433326239326530396663306563323062393366663366 -64303230363733333030623737623338396266666339383234666165643964656233663937366232 -32343636383731326265316633316330383239313139363366643461313639386265363631303034 -65333136653963363133653163326531313738643961393031626439616139373233653062353534 -38623361616362626662376336353935323563646535623336333531653561363832393938373633 -37656535316366373732323965633033633730333332373932323062653734646361323535616239 -64666433386635323733663236346662643738356662363234356437633035656564303131396636 -36633533396665336630333037383035363434303730363731666337633432656563313136356636 -34643734336437643136663833343464323234323233343766373030383232323433306638646365 -63343366333334306634613464613665376234383961326430303064663663393531636165353363 -36383063306666316134366331326632646231386137313232666364356434613133376561663839 -37623935663461386130303735326234356432313130623961356363653464643031663736613037 -61616230326465306434663261623065343639383637356233316332306138353061353931363066 -63616638373964356638306561356638613130306337643966313032333833616532626365333030 -31353862653939373436633766303830376230376266363763616435326163303732373237306263 -30623161663632646665653436306137303034666564643832633832313335396434633633346633 -35316137393362323365333166393934366630356163393037666230373239393165333839656137 -63623766353764396530386133643230313265383933396434643536656336343662313037373531 -32353539656631616464383436353139643330636164373532373638343564613833373632333935 -36303939643762383437653537366431373161326561313832363163366631373535636463626236 -34333831326334636633363032336361393936343863636337343538323139376637643866383138 -62353136663332396633666337313738343133376537306337343938313930656630623265343939 -36636630663662393565663134383430306436636338393638383062346264323034613231353337 -34663732613038633165313066303333393531316433393162643035656433373462616434666130 -63623931336564633838373036386264366435623166386564343931396439363831383132316638 -32373965636636366666396665373263623231393238306666383030623437376437366138393536 -36373266643032653236393462363039313330646331343339376166346333356663616335623236 -65613139393334653161376331626230303231656132373435326337643961376535653264353530 -34656462653239356130623233656139366534313335333765386232333439666230326266613635 -39366435313332363335353936643434363230646634646339613132653430326430343230323433 -65633365636231303830346633386639363039383063613264333237386233343032363030306637 -37363761373434326463363961353532323230323762613130393732613031333931346362353932 -38356162613765383335656563313039613239663636323938313836636530366264373661643436 -30303439363237653066643364356265353134633838656162666536356134626230613162333065 -65346438333833666465613235366665373666393634613963363738303434366366303033396230 -37383039316331653039376431613739643933396563613566363862393838333839653336653334 -30363530373236636134386339653031303931333237396264323133366364326533393035363433 -64326338386265376263366566303365333537326530653734323737653935623438626431376266 -34356334383238303536626436393065323066346137343935386438646231623839336331303739 -30323730316534626165313861346362386534333737663533333465646234346238343564373966 -37366331316462353632383335303338666261373139393338363333396636383366313539306463 -63643665643038666139376266323264363236303161323865343039626232613138343161366339 -65333332316230616561313038353865336337396336636332356535626362613033623636373861 -33653639303763653637333933343331383539663132303032613563643965663832653462643766 -37346632653030653737376638393338633136613730363862396337623166643363663138613164 -33313938666563356531636635366438666337373331306233356533346236623538663363326466 -66393233663931643536663264623636383631363763353334666137393361386236343266613165 -39346138386139326362313330326533326663383033646330633163383163356537393539633437 -30333562303263346138643737623838643439623564343731646265356162393635313964633638 -36636238656664323931653564333836393234313634626334353961323164383939663632343164 -34383730376538393139643633393238646236386535643137393735613738343366643839366164 -31363137636632396139616664393164343761343963343831323737663966626363336162656663 -33323930646435643662643132313431323164326631383665363634613637356431326561663039 -39373137353932353633383237346235666466306664643237303765643536373665353638386530 -30656264616337306636373235316661333065663334386263633933323737666636346630336566 -64633361363466633136346337313939386563356536393761633835613863336562363862636262 -38343033396561323731653737333332623462376361656164326136363439663930663932353838 -32356539303066646465353134373538316434653936616336363136393235616264353233386234 -61653665643062343635613633363864633430633833333831316438633239663163376235646339 -66326465316236656539306239636438313231363433653661356361633835383538613361653237 -61646236323131363430383631623363383937346339616163376632303134386534326533643263 -63303961333731356632363536636639663436313438323730343637636331623538663238316362 -62376238373037646466343631326566373865363164663664643063666361346139393863383461 -62376330383233343363336434393038313238613764373462316231396632393562343337396265 -65636136616361396430633063653433366465393436383264613330306335626430636633353336 -61653262303538376135383236633238373434653566616232336136393935616134623061353634 -33613735373637646632613238633963343930303134653266643736336538623235303530316130 -36333665366562636636646336636362643330346230393733343535663539313736316466343333 -31316362643961333532656333336663663834373738643137306134313639346138326163666231 -62636666623131613534343664323636383738333562316430333830616164333662336366356338 -37363330613639636231376165643162376132356436376437613765646138643761393532373838 -61356632656538376365656631666263373537363037346666656138366333363161383033323630 -31636330346135393735646162353964643334643135323939343534663136663864386265653230 -61623461386436313363653765643932663363343335313536653437373931303137333434383637 -37363130333836306665336136376362303566303663373334336161646439303737646438386337 -36613364336432373765376235353636316139616666613836616234343236303666313731306238 -64643336303761663237663734303833323963313132386661353830343662323333393035363931 -38306265383561636234626331666431623534346333616566663235636530623266303661663536 -35653366623936616462666333383733356139386263633066323235623737336434363534303165 -30303036353132666661663132313634383163656333666563353365393636366236356639633562 -30363031366463333635373462643235636434633966346563616130343762386331363763326436 -61326661613433663663383761663762653239656166656431613138323835306632373436666539 -37326130363734316132353065323862613838306632616265373537346432643131363663373632 -61363231666466326139633837643566623533316361663562653333356231633165633732653634 -61373537353830656537383836313335623139326165393035393162323736616638663861636430 -65653934666463646561326361626364633435666162393965376264313930636263303866643934 -36323431386630623236366439353534313463326234363637313530663733353237613263663239 -62373663633539613764393462633431383237396636653466656561313231643931323061363933 -64633066626566326564376466646266306661376131636133333566633232656636363162383962 -39346333386461373734323130326336313462333363373536336666636232633033373466353030 -35363738353063636332396165376434623662363235336461636130353461303264633236356564 -33343935633666373338346337303339393265353139613730343935373335616438306432343836 -38653734643436663261373063383462366533633430656366356132393530633563636436353565 -66326564656264376535393330666466346465623535356439323263373134653536623866363834 -39653164313730323764666232323362356164353666363832366535336639376135333565316539 -36313833306136376234333131393737313438363235623131303837633338353034633236376536 -32306539363961626631386133623937633638343731653837643831323634653834396364636137 -65336539663530393833336135646430313430656365346365333135633364303765613634363230 -33653331313831663530613337386134326265396233353532383330343937643738383338316466 -33663761306431343663356163613132363463396262616436353539626130643335376232396562 -37353164323265336537303966353565306562643339623865306364323831323336336439393038 -35303132326539626465386436353062626436313334323566323762393064313232303962633233 -65326436336363386336636263646635323535316635353463313162356164303163326235623761 -64643835353032653531343735383237343830633236383965353238636430663433396531303235 -62643437393764376461623630653033623933336236363033653835336139643933336362376632 -36313632393739323433333333656661316232386666366133346535346261333538666434356639 -35313830343937646634653533623635626666343837396366383363333430363237386332393466 -30303665356266666332646266393061643035303139653439323131633035333038656237653537 -37646166656336346634633438313339363066366337653739333964623764363761616239633165 -38643635613730613866633231396435663362343165366133396635333933343666646365623539 -63333531353136636666303535383639393434313236333863323839383835653461643635396332 -36386239333166616465653863323036343433633361346434363033386462626539323738363865 -30363463653266666231353137626439363837353837663166316532633736313330346632356164 -39636137396565336535333366653436323065633936353938396538306566663837643062656239 -31623837316337643937643564396630653634306232643631623736323333636137323037613438 -62323062626665613465613734616536316533396131633131633366373164356165326135373063 -38393939643161396138373434366635643131313235656433356639663663646665313635646539 -34616433373239373333303434383736356565333461653434663562333538663331626133623464 -62353631613735316236373332313635623566396230343132613135373962383366316161623761 -36633864343032336135626562366463383838633730383961316132316631396566353733393338 -31356439616266663565626234643935363334663439316163303566653566623132373136646663 -39353030333436363536383661363332396462303764643362386435353964303263643066336236 -36316137643130653161316132336564643330343935663730323633323035663334613838343162 -30653761323065346233333834383931666465613461353335353830313765656432313462623435 -64306662326239623137396639306438646531323264363635366362326134313262353330346362 -34316338656461663134376330346335623330316333376331633265363964316531326137613139 -61323561383731323135336165643437363931393537386330616330343232373538646165386237 -33373933393530643961386561346563373063613237323335366566633364343432303734333737 -33643165656437616363663734326164326439306266663962343964326633333639656637663761 -62343536393764653239336234343631633531393361653439633632613039623766356138326238 -32336263373739613861623364656239626366343730363433353439396236323233363838623337 -63663833346161633838373461396163663765656236646362623539353264346337323232646464 -61383338643839393266663535343565376661363562316631313231663139616564666666613331 -37393931373838383865633539613239313235386265363738356539383766356262306536326339 -33363737303035346262643831353763303662653363613361623636383038666561303562626135 -38393836646563353333626631353862623733656561636334653230656362343763613331306136 -65616535393038623661663630623837353030323634636263653932336361363064663661346661 -38646339666633316362373262343166633166313436616535383461346266353431326635393737 -66653065303833386266663765393639393133663136363930353033666365636638373732303964 -34653231363266666632633737316162396565653830313930663265386634306637663432656134 -37363663323662666663386339303132643631316135623561646665643738386638353536613165 -61303062306133333338366466643430396666376261663639363465346139656565626630613963 -32346631393232313031613432633137393139393732653665653637343765636233663338343666 -39353431363461636466653763646231323936323634343930333735663038306232393133316632 -66386634393231666265353662393033653963326131313162366431663533363634373433393261 -66616238643134363536656463613937366135353538393133653161343137623364643939366263 -33383865353839663464363363663163666662306532666139313533306630313261323461306132 -37326135643063643038613936353831393262376534623662343565356436386433663266336130 -37663437343463363861383836643730343664376633336636313233663265626561646237653363 -35353736323639656236623437386238656431396334613666376663363631376635343032623137 -66633263636162393938333732646561353861653635643637663932633162303639393939643438 -63383031646162303732653061663838396430623339303561666232323565633839643831386534 -66643938356232303838323239393038633138646165353562306333356536353165633161313162 -34396434353335306663373862336665613161323538356563643065393666653334626638383535 -61333437626336386130626464613162396263316466386266613936643035636437376161663133 -37383232376331653834373338343864633232323062393938646534373236383337383133393661 -37333164353866636666303738396336316234303834633561616536366563643864366337666330 -65623236393433353939623562363637666661316436663739353636373938363631623837363866 -61343137306464383464623339646238303964303239613638386336313135303831366665326463 -62626265643164626663653338376665303733393436373962376563663063666262633536653736 -33373766666562376437643665393164613762343536363564323539633835356464393333653864 -63393364386238313162393461333362646261383335613330663931613934363863666633643138 -31626562666265393664373337356531343335656430643866636564376231663030313838346435 -33323232646436613966616236353034623637376364313838326134626132383566363034643635 -63643133373663353636353231303963653438656135663336613234653038623562393064336335 -33663533336232333030613636613635326533376563656436383539623261396364353837623761 -61343239373963313866393765343639326438326139336637613737643537376439653038306366 -34363036333430316530643562376230343537303533653739326262323761303464613563393634 -35373538373261313434666462303038306536653238653432353933373366633063343136636331 -32643238336332366661306538343365303630326635326237353362333961323666316639393365 -31366363343438666237376431393835643731636164396264303464653430353031356262646332 -36316238383162353339386535373239366230616132353637666433353663303131333864303739 -36333838313433363264613063343437663161616664373537343863303464326265363763353731 -33366166343138383263306437366338633333306133376464616339643365326239393930343836 -32313636383934633832613562353436353030353262376339613464313933386435313132376637 -33396636663566376530346130396534343836303336633562623137636636623965646362393432 -36363134656436336362616134316430313338373466313865613836666632616663616134613337 -62646633303435613131386631373236353262346362393732663431666134313565386233656566 -37366136363065306461376334373730383930383462396161636634323635666133643564383639 -38396638663532366430633639356134383862336530623531373763306431323064353536623930 -62353562636466353938393365386461663065626130343164383236646665613761663261313631 -62393565613465643239373765613039303635633761656136636230336363643635356538396434 -65666261663362666336303361636139336437393966373963383332643231643961303239656630 -39396266346139353731626364666136396533393765383537646361393664666331306539373666 -34633632326262363963653536316235346162366237333832306337333666653163623037323862 -38306165333561653738373563656366633864646465356432356430663932323163613332393662 -31666561646632373764616663303765356461366366633862373562303963303166653462613636 -61333935666632313066323561653361383531613963333830303739666535333062623638356165 -30313331613538393337323364393365316266613266373331323161383262643162306461636262 -31393032316236356133373832323133336237613761383063363166656363373233313461396465 -33346533373862636434363630663032386133626534303962306161313237326664383335393631 -37643338633236643534356532623964386535646530623937306163356464323162323665336138 -64666132633939323231383034383031343530356132343765313764393561643636623633623933 -31366265656135363639333463383436643230653032393465636166333065633938303063653032 -36326134646331376135373861393864353562376238643862626164353138393864643439373238 -36613265353131636335386231663935333930353765383331336362346334326134653336613931 -62393335313434323835623863663532313263346431383966623937333339396432623536376466 -34343236396639656332393134343965323839383731373134653337653535363265306437333765 -66353238653565346534383364356264636535613866633262353264386264636434326562633638 -37383164376231333138343164396664626433386532366536396163636239363530373632376639 -64336365663832313763333963326164373833323536323166326264623739656266353765353131 -34343638336365653337613162663034326334376239653434306435643261643431663738633466 -61373336643961663034326361353033656465643762326333396331666531636632393830666130 -64616337633966373665333866623533313361363833653530383434373132616565623465363632 -65383139646132633261653631313364633034643838666432626637303436373839363334626465 -31393964636330343931313336333237323137343862613130373132636365323761326333373039 -66663464343737363035396530646264303238323330333361353334656232356636616536313262 -62663462333363343165663337393361356365336430373430663931633039346630643934623435 -32313539343166613566666531376139356637363964316130666133366463656333653834646433 -32396632636135313039633238626433643963373238343932653266363930303030333539643438 -38376464313064323761656662323135323565356237643862373633323931383034346531643162 -61663238366632373236383435643930373061303531343838366566386537313338633539393439 -37646161366137353464646239336235333739663838356362636462666132393533336465336162 -65373739386533613034653139396537643438306336656633663335623061393637383163663361 -39326632356232636633363733646539323662643266343934383065396238663037663336613737 -66343739396234396564323933613437383233646130363038663333323234313939343232313236 -61636239346539646363303335316539653633393330656236383334346534356564373166343064 -62623934626161656165373731363963343533656161636434653631323565336439313566356237 -34343539396432636265346339353163383139306639653661313166386334353865326339353133 -32373063323665343038636562653366643738653534343663656633326630643330373565616632 -32343837616163316234373563333137373036366630303763613238323935616135333064646436 -30303636353433336239323939383731653665313733376437323436396463313863316661653764 -37386131356333613862663030363832336465366139346534313933633031333362343534373262 -6265 +64323630356530323565313638643038336365663661646134393661323861343032613933613535 +3336353562373436393366653331303666383462643962340a386166636539383963303962393138 +35383638663636396334326533623534623866663863323535393162353764343931346632623639 +6438336334356539630a626338653738653639373837353739383561373634643466306536383332 +38343066663332653766323137306234383934376435313566333039663134353736643133656437 +63353639313936343033633935666535326233326436333265333561343636346261653036343464 +30633861613034653662613535386638313936383334393666656632643437313161386432353364 +33653632616133353162363437316465313534326537623136623733366164663964643861333734 +37613963646239316336326262633732393237663433353635643233366138646135643365383233 +31393835356635313032306561323435396461343437343861326431356561326232616634393234 +39313035303635633763613261386164303833306634323435303166613736376137646533633161 +32346539623862396465613138386231646439363764393337663535356166356430343334643438 +39653834393566613763643136376666343330643438313537656330316664346239643164663732 +66343130386363363232316236653432383062336436346361326637396664336261626263306530 +32636662356465393336303263653064313234386362643030646461356639663536333265646633 +38343639366231353061613861346361396132323530656531386336643839306235313265633266 +61656237323634306637383430383365383361346561383466336165376132616463373430376333 +31383765396265613633316164336536373063623162346666666132366134316361333837323433 +35313066643366396636363633306162393433653162613661653262643937336361323431616136 +32356162303638306566356261353935363036373837336634373165636533396433633461326137 +66653331636430656435343539653263306533666430666466653563636334353230346366383062 +34323031666633633538306561356464653331373439383835636433363362303232653462313238 +66626563623364353765363665363764623537613838353262653435376630333632303732633730 +30333631646633363530656466633564386461613763373830643063633366656139373562383662 +34626461353537356235343939303862383332383136383265396334636232376630363032353130 +34393336316535383664323636613231643337356535323363663562373234336165303163323465 +33353062653164353031346338333635646238333231313562346661613039323133393737386563 +63343361376637323332623361323762353135663661343231363132613364643138616133643666 +64666639666332636536626130643039363934653535363166313265303037343735343165656138 +36646163373233343332373538366266313065626562623066343763386630343930396264396538 +62383966366365626530343934363935323138353464306264323838363264636261663566653237 +65343132663239303061326265633739653564646530376534336261623264643466616633613634 +66396263313963376266333430333361383336613563373162353534303731333332626539373261 +30623930663338636236633265656338613638633536646662333838396633626465303530373633 +37303864653962666165633336376635643466343230633134366639656137643335653164666563 +31653933313865633730303934656336353938613365626566323033363464313631303836343962 +64363831643565363961656536326332323161303933376365393061663462323536633731653039 +63393036366336363233353236303235626162313536663130343436646133613032333863333862 +65373866663830666338623535303865383763623730613839633666383038383135366139333435 +63613731353037356462626536643862663934303934396139626635313964636365313563313466 +61333032373538373362336336323637393134333830633338336661663633363733643334316637 +33333632313237633564306539343239663831396435656237373361356366393835306663363336 +64383465386237333131306264323032393130653066346531303133386232353566643933663031 +38646433396135643463363338373762666662646533343131323133656164393037333831643864 +39663831623230646139386564376130373661313239306563363430313230336564613066336536 +66383262363238353137316538303332613330633764343735646630383863383331316232656631 +66353737396438353538646266653666616365616437643239316336623238353862383430396230 +66353439316633343731326238373636636365356530366364623931393037356462343535666139 +64383134393466393663643531333931393961343135643866303564353031396466306365666639 +36656239613832343638336536386638303961656332383730643365343739306134303932623463 +32363230306137333231393263306131366235303765643565656633383638373065646339356335 +62633837363265623337376138636264396334396430366263323164386261393866313639653834 +37303063376638316131363930306233663935383131396431653034626637356332313638316462 +38393931306534393931383032356630326261303638663938663830356338393035643234626339 +32366533613239316431396137623065343235626361616232346539373832343536616639363438 +30643964353364373539626164363237623037616430343563313037313534336536613662666562 +38343233613535623532303362386230653136633166646163373264333865323362623838363335 +63333562646563366134366634386337646433343630653863326563663666343337353433376531 +66313766313130646136376338303632663765336132373866393163613535376238643532313861 +31333331333833303539366437343764663534633039633162623466323763353033653332363665 +64373161643038653334643537663164653864303134303638323534643635383337343266323337 +63633865633564333839356136643039653764343636323436353966333839623231396336636135 +37623131383531643261326365613531333934383564366566323761346337356366363233636338 +63656633666438346661343230653531613037336331393866666437376366343434386265666639 +34616261303737386437333439386338333836633261393537383633626233316237663561323365 +61393236356132353431363831306638343566633337623965366663393662383135303136616265 +38323965393835383530336534643064623365383839343338616365623964633962363366323462 +37336534613465353034353036646665656262306634326235313633356563623735373463663734 +66333034646130323638613838356165613261386161386661353137616230356166366265323132 +35373734356438396464323266363063633136306533643462613139336539326539323563396363 +37363364373962643638663036353766386136623530313233366466633362356135366332316238 +64373233393031396339386466656637623332353335353837653562313833353432656337613937 +61333430353066313366306633383361303565613030336561636431353235626665636665623735 +30333339363531346265313064653733333164623961313632323833663761343333363236343839 +38353334393365326661323037663366376264366535363266383964363431653037663230633839 +65633063343432656432656230323134653062336161626462376131363138376332343837616234 +64653738386231613035643931313066633561643732373932616261346435343739333662363137 +62386639303533643738643434643564373838366432366663653632633030643434613066633630 +62373065376339393939643635386630303562373735306239323234343066636636633734313230 +34653163383666643061663963393331666432306336353737346335663939336239313364323135 +39353632663635393037376438653236613435626232356231623939393766393766366433623031 +38376263663435366335333236363365343539303237393130393865363435306530633731666564 +61663265366666633636326638346230373962383030656663366565393535396137666163653963 +66323639626437386430373332636538376630373232653536363633313935633265646362373233 +61666138323536303661343863646665636661613466393362356132366361656435346363323530 +65323764393066343036623661353730366465336564626431643762663330346262656132303932 +39616566393735396533613334336430373036356636393861353635386435323966613631616138 +36363032333738323839623765393233376433646330323466356231363034616433323534613832 +30323864643838373933353264363435626565353066643037326437336130373962613038343434 +39336431623437323165636130373830346261346661643036623965326332653438306661393762 +66646534633261366266383663323964323638313135363662303033643065376337663065666165 +63306638393465303632383434373635626534316234396563376234623934393830306331636362 +30633162306339383032663634303761343265313564373965633338633838333465383131636534 +32613866613332613438313635373534616339613366653138373131616665643166666336316334 +61396137666661313562393135303031356231633338383431653338653166646661373333643061 +65376630373563643530363731623136616132353839663535306435323362386463346264393563 +66343763353039303938366338633961363062653338643266336664366537646330356364613732 +38353636353739313331633336366231613132313436386462613263383837313038653935343265 +66386365663366393133646230386537326336343332626531656530316561373132313031396661 +65373238346365636437623730386637633763316539376364656661626161396432393237363434 +37306433613366336636303236303732363137353637623736636165613232663139636535373334 +38623538393939336530626331373837653930633936383539663835356532613939306334303031 +30613961663238636363366434373037383665326561396331656335346561326531386462306433 +36633663326165656335396638623563356137623031323262363761333331316139326638326136 +35303233343734313534333662613766666434396434373330333739643234636361363131356537 +31346162356661366463366131386131323466643365666434393039626139326431366630313839 +31336432643437633963303130623831373533346163303439343137316438353165363536366631 +30383731336431383266393235633639666539643136643438303038623633656438613065336563 +36613862383532653461306564316462326461356434326436313235313638613066623435373532 +38636566376435373462306361306435626638303461396639383439666165373132356264383764 +31396632633639313562623736393163653533636565656635343337646639396166326338366137 +64373331623466636333663831336164306134333661333638626332336232353333383561626539 +33353339623262613165356366353539616137396463366334666266323834633830346166316566 +39366235616335663666373631613766623462653763393735323336663763326365633339346136 +37656336396665343933633961336466613337306335346535366538636664373738376231343566 +65333837323439373565643964646636326130656364333539343530393832373234666237373531 +65653731613930306634363838343632633762646365623364316635626466623436303732386566 +64333834313231643366363238626635653938396333663264626361303361356534333665373337 +62636530313661343162626361346363356236383163353639313730306261393932386630363935 +37663132373638323937373330663837303662663061306232303365343531323232316634393237 +66333331313766646630366465626166626266316236633265666239623037633062613865393339 +64663861646331303837666434363862653063633161653739373664366561666663643234656566 +63613133373235613239313537633634633137666636653934643864386331313538343266346562 +65653763353161323764333837366430623736363030346464396335646463366463623766663638 +64303831656262633336376437383065326163313935653165356638666435316133376666616139 +32626363313763316562323565393266333936633931393863326430616330303766666637666435 +38376330623161353336316465623632313335343861636661613630306664643735653238363532 +66643530356162616335653439393038373765343164366666343463396462653166336261633266 +65663165316661643733323437613866346333636265366638306635333736393631393439633538 +32613461643336326435653636666261386335636665643133646131343262633262313861356436 +66396331333366373833633730323363306633366466643731626665646664333364326435333533 +63356334373833363334663330303939656531666336643366633231313739643163363162346361 +37323131323037383438313230623564616235323131623837383132343566633835626331323430 +38396566623230326364336566303930313464643830313066323763656637393064396530393239 +62623635363235656535643336383137363632623738373133343936346438623636353530303032 +64643035383732656633356266626161653762343731393335366164656237616636326336353634 +35363766323537343737656131323934356538393934303136623435623364353937323662303736 +30306330636431333830663266346639653766313033653235616464306231323032323933613961 +33306661313763626364336161316536313436663666373934393762343836396139613438386533 +65656139663235343333633736623937343533623262613830303739643830633565326439326262 +38346138353762306430646235306363383130653565646336346665336435613038633361303339 +64653365356634623130343735613365646130306535623436653531613465346561653230346133 +33373733653561636362326264633431613334343764346664626333393833363734613831363634 +64633831633232396132306363316237383739656537626363376132643637323335643032666464 +61643635633632643737393566383861646234383134653233313162363564313330653138386330 +30633339373132386662363163396630613539353832613039616531336564636365356533643337 +32646335666632366334663165643264343561316132366538356238366362396264333235666636 +31326534613531616531303431363562316435636332353538636666333465613536343337366530 +38333664356364363235373231666539626136323631313536313635633463366636373464373530 +34623564656538643064616439386631343934636434666637636439393263663230326165396136 +63666661383461653033346466646661386636376337636535623932346534393261656537313933 +65333332656233643639313436613736343433393331663734333331373930333533346435383661 +62356537343835323237613465326662613262396435323533666164323961656534643264333836 +62313432356265316632643063663066313664623130313631386538306431343131336363643764 +35313336386333343937633033306231353063326663323331373032356161356161343235666363 +37326130356530663061343134613331333138336333323532396539393062333761383562663939 +33363363353932336337643230303837626665376436646536376639306164613938303430353537 +31623030336630313964343266356437616231303838633930353661396535383031383130326366 +62326236666162363164346132613031303734303462323733626334383665356263666363623238 +64303161633930623266326261653066383161613766383465366235323066633539613463363466 +34626363383361373538616638646565333832396437346438336566653637316137396261393164 +30376533653766663737353566316361353639646539323237626639303430326661363137346531 +38396236326432353932306462623238613530313437663035383631373963626333613539363437 +30393965336562303563333536393136353231633634653333646632336365306538643038626335 +63303834306233346666343030313535336139333733323765616439333464633231666665326437 +37383661353336613831626661396536313465366264393265373232653465336531363036303334 +64326234653531613438663236336663356534383134343765363535393065366531366262613034 +35393835343565343034646565376432373439666534666463323438626637303565666461636265 +31333263663338393066616465393734323031336233336239323833356663323837626436366565 +66623237376238393338663231616631333632626131613663663637353831616435653461626535 +65343362623661383461643866333363633462386636636638313237643734306330323666363437 +65623035323866363439383266353663323230353537306138303238366135383965326663323634 +62343633643431623831616631666237623964623063643732393564633938633330326561383239 +37323464393930656362383064356536323331623835396334393634353061386666366434353832 +31323737373165316536613033383162313736663663396162313837343338326466636338313536 +37373864333364326362366633303165373030376131396131636430383637663837333430393134 +31386131333565333362373863323764383437656361303333633531393166323538303637316436 +61646231653836366535386566363532333437613561373962663234323534393438643535393536 +61633334626237383862383636643061343336393234653230353465343439313731626538313663 +35613264653661323264616631613965346232393662623534633864363532323631326338366135 +38396461663532343537623163323765336537623364636465393937373639356662643432373063 +37333834373963306435393632303262636437653535663537643039653966306631323262356430 +66623933366138623562643466653135313164633731383062613662336439633732316632333939 +32336162646563633433653966653030323464393566313466386237633663336131633865363332 +61366534396463623536363866306366646166323734353965666239616635663135373638396331 +62353037383138626565343163376564623733303166386430646130353466353836653862363832 +61316332343939613833316235653033643230333761313937653631343061633133643838373039 +38333339313735346564363961663238373934633562653062336565336533313836393230363133 +37316231633931623631396334666434656565613137303836633636643532643134646631313962 +35363132653938346266663332326665613234636664343938366135616162333134646536356639 +32303633346139393166393565303865383334373332393266633264396666383139343163326235 +63616262616234393439623734636135653532616635623065343839363137313631633563376338 +39343039663865373165346435313430313063326366623763343736343435333036646638323061 +64643835303135313431663334366538616130316432623535633531313339613736633837636233 +30626639613539313335393532353437323234393364383465333461623365646161366363666639 +34663233343539643738326432656134346230336534643530636664653330343932653131333031 +33386237633030356164613630616363356466373738323935353463613730666265393437323535 +65333230613630643933633065623766306461383237326462363864326639383464656232363131 +36373333636265643433313235343966323433346239343434343538323633313730643564313230 +36373332633164646662323130396261383762373662376137363530663736616562663961323866 +35393835343636646565363935353332343931663062383036306264313538396561303932303963 +34346131633733353236363036346131333332643765663239656332366138333231633536326432 +32373339396663336535303135326666653532343465633161393765363364333030613434386634 +61383835626265303066333761646334353130613565303166336661623234643933326134363532 +65636564656361373835666439636431343261333363326337616462326633356164336238343861 +65343934646461663566363733646430326563323131613464613834316362386665393266333433 +35306465383330643733376466646336353131306436313835656536613931303235343862343863 +36653039386535396339663163623738326439356639623231373030636135643038313665333761 +33316131373838643361303662323832303639326336383031336338383436333338623232633438 +37323538333765333330356366356136633632666336353434303062656566613832636435313238 +32393836633133346336303335616639333837666438336665626537633831623936313137393730 +37633563323862363432306334363364353966616438653333303036343438383031346261613830 +37383931623836653830303262633430623131663263363532643539303936663633616565393434 +66333738613138343665656265306363626264363435393432363634636330333635393231383535 +64313434353362633166623864303733316536626639383665643336633432636132653834623464 +64393233306564633835313934336231653737343735356432376162303962373032333164323064 +62393362363539373031313330363739663563356536663935306535393436626364363537383663 +38303963643730656432323666643462353761623634326564333563393239616136343962313265 +39373061656133393135333239316436333264373131346633653533626361333636376431653431 +64653235303530353630643535343632646637613730346137356137363163656136313133313065 +30383465323032373234633430383336653539396265373761333838396666343835343235653034 +63366463336633616666616465613764626530376363313538633963383638663366643336323732 +34643763363263653965663734633263366133663365373038373161366439363237613539343632 +66356663303739316632643436343139383631353264636533303333303438383864633238336663 +38306566663866333964616562333333623363383434373437333533383033646166383938326233 +32386234646535393537333937363731653138653566313533373731653863373663386261393639 +63346337613739383361643430386636636465383932363535656563656239626138653137633864 +32343333616234623765373330393639396339363165316531373062633233343934653766303566 +34633338336236393965336239616465636535653139303838626535613865346163353633316130 +61333230656362333833613432646131643836636631653761333563663430323964373432663164 +37353232343236663939336464643966636334316561393530386138366662346537383165343635 +61356663323062333365653165316636333134653563306631653538326431346535636438346236 +34616266376539333534643336643161626232623161636532633634633939373561313038303837 +34346164346361623731356264653031353736396530313439313836383237313639643765336662 +34396638393564396335643466306434663134653565333761633766376564363665636437353336 +65373963666137626630353239303736646534656235313065353864623631323132336531383739 +39633031316538623334313132396536373032316630663631633939656235633930346661383839 +63336665643137373432353964316564326366623737366165666533346166653764333066396338 +33626163663732393132396430373163666463373132313861623331363930373637313164393632 +31313232663661666562303533303862643436366237633335333035613235623638343030386436 +39613165383163323964323231356236356265353462656434646266323561303934373638386137 +64396237353464656466633634613339333861316231623833623737386665316336636665363864 +66666265386435623431323032303262646163303762373666653766613664633535366164303237 +61393438363739613536343262663330336461303563386561643338353262363361646363626535 +65626363333331646461613365363734366136313230653735646166306330353761336438376530 +64313632643539306639623362333032303033656361666366643366393938363564393565613065 +39323935356639623438393233643936393230626333613163356230643532376535306234353665 +37653737636139376336656135396632353865653033373334633563363366373933633635633165 +37333266323939656636323435326361303831373636613465646162623766616664303265386332 +34383030393561363764636337333838316437616432376330613336303434666261326231306265 +35613865336433383637343334313639313362623266613765616135613735363633306233396434 +61633663373630613838623033636538643233343538376563356462663434363137383863376536 +33643131333939333633303131303735643662653662643066313663323161313964313865396233 +62653661373637346636623135663133643436633830656261376436363035343538303534323231 +61393034326531303062663563623330323836313436363032626565383364373735336530343238 +62386266306638653066336266316463636163613137636662373131303564393537613162373632 +61616531353635643836316332366135636637396364336163666532636461643166626337623235 +62303135343563636632626439396532383934383733623630346535636461333165643632616139 +35303130666233376362656235393035373666643963636137383066653932396533306233396437 +38663231396438663331303931636632323136623637653535313335396336366330356535393532 +39646531303766346465316264353030636463386635343966316165316633386236633766633361 +30343533646537623135333532363835623062383339633037323166613161633466393837613566 +65396532363461303163663762666138356536636337306533643831646637633936373361643338 +35653732353435623733326264373335616665316635663930663538336363383630623632313762 +37303730653866623762306638643232646663663863616235366532316133643862363931633234 +36373430666161356331646136346164366163393462386539333561663831323932363564363931 +32643334316132303532646663663461646133386630353139646530363663666635303262386432 +32663963336238633837326339333737656333653832363339613861353438383163383935643831 +38373466366135363062613566393462393063323730626532343832333031636632626461663035 +33623433373831363935363432616665376236613535643137313466623038646365383062383736 +62356138316466306563373732333161306633303936333163383538663033376666653632663431 +38363962323530623233323164643739363937336164656537343936313430636631393838663436 +30376137633464316239666137333262663034393138373533626561663962653332376634396262 +32323732653835326136656331616139376135343362373634366263633566653336343262313966 +65313265356234366566313330643036323233643761336463316331393436353032633437333361 +37653631346535616665626162616265306636313664643164363161626131303634316263376231 +36323336623930336334316261663464386435316163313439313162363031326337393733333836 +39373866656133393738313434653161313036623964666236633736616563373464653462653633 +30653633343561633336313430616138636537333532613764653064653931636363336233663537 +33373732383665373532336561623238353063633762653632636633616464663838663430383265 +33363530396461386162356465623963653737323033646233633866396364323635666565346430 +66613532353230353635373261343130383137353635373532663733323339306632373532353839 +34346263316361363265333434636662366466653562393666613565333536666533343437386662 +30356439336265623165643663313964633564636365643161336163363339346262346338616636 +37623734353862336163613261353766373861666261623466393765343763623631373862313030 +34303232303433303636663136386461323564366133343636393130333837396431653365316566 +31373439353032336263333035356633623034666262323031363131393035393630303439393531 +37626435323238653634373930303064356662346238396635646133613633306430346661383061 +65316665333766653361373039323835633562663135633032336338343835303364323033343163 +37386330303130313731346230373061376565636264376262666630316536396431333266656361 +31336137666566303062353933343462356236653439353861376564376232303935386335343133 +66326665663035366232366563336639396231346461623235656336633131616138643265376161 +31396365353632663331623262363265366432353337316638303039303833653039306235616164 +63383661393332646561666466373765633538626562653865316163646634363463613131663334 +31323537643366326263666366353365376563623366633935343034373965663837396637303730 +37396266656433663032343438663633363733356436323763623730313338633964313830633161 +64373531333633336332343838363333663734626564646465616337393161663364663733316562 +37623034316464643037303038353139663038303131303432346365623931346236386632373336 +61386539346461653066316435633065663862616435663361353335633436626531393036326432 +66623331653064393162643862646435633437663662616630363364333130383361393136666266 +66333936323633346662633232346335333232363966663064616165666235303232383863346638 +61396165313633633462333839623939393565333538353261663738663931663661623530393035 +63646132303562333530636131306261376630656264613639376339313932633531353237323037 +66316161316664613339626534373136393038396661373266623139383237343634343966626561 +65626439623765343232353264616538376337646431366266633534656664336138663737383239 +66373066383433323337663038643134363266356265626136613239626436636336363862656165 +61313735313933656562313334383864646237336438623265636165343734623436656661333937 +61623365616562636337636536376264363330633935646436336161643835383035363233366166 +34663930643063323539393363666433333365356135396432343935396166663961373961353663 +66373230633330643136303536626336623630666633366532663530633161656461333336373463 +64346261303765616134333132636439653962386665303335333737373632353936323630353961 +64623231386331616237326466623165636138353438663136323961633036346365363664333131 +35336262646230306337383432316536323263626230393633643939353066643339306331373737 +32306465633864383666363563373431633364323161316138346165306232333632323536656365 +64393036613066376437643237356362316338633262303631313838326164373835653931336233 +38396636323765636137316565346562376534613835653437373333633761643164316361326131 +39653934306433663366613465613966313537623661346165383066346661306239306132383466 +66306637633430363432373739626636336330303330386239376539643130633065383264363638 +33353962393837653433303033363966383830333838653832646538643164393432396565643563 +62633066396334363531303764646538653832653161373763313266626163373233653030656164 +36313634326365623462313563323634646330626361396236366162323138623034626236616531 +65623636396565363366636165383238323961373663303036633630303438666439353233336532 +37366634626439653834396439656531623565396664376666373132363232643864643066613162 +66313932313533623033366165386132356439376165643333366336303561373736613537663031 +35393432636530653034646132393133663732313361653036646436356564363961353138366633 +38396238316437373831326532623038356438656161336137363461666136623565356637326238 +34623566343565623063633536333263633830303361353131323965303666613662623464663962 +39353963323563343561336137396532323839396538313230613464623839666563363761316438 +36313936356331393166346438613264636163363039373333383232653739323236333830333064 +37333733646130393766336539653139346337383266616337623461333466316631623964353739 +66653838633663396338386662663262336664623061383233336230646136373263656437303466 +65653832363130306362306533343763386236643166636236646362316162343335353864623735 +33353433633239376164393965623330386462633430616337643832313137306636383064316262 +32663537663065366134336166653133626137623932613433326137326362396233636630303763 +31383734323965646331663065616232366333396637326631393234363564343265363562346432 +37326137383262633138303236646236376664303964646166616136346236383437313464373762 +33376563646264383235353830396338386161623934343266333262333561653737303865303532 +30663739313038313433626533306230626536383263656539643633643438346665646438373437 +39306636396434646439613536663030383433363431336638666234356532396532666134353865 +34376137393663326232623833323262666630386231303166653766633661313634376232646431 +61613464636438363462616463616238356365626266623564303463363866396666366361623862 +65636563323461313664643232376566643866616634386338663535623130326462636366623530 +66363161623537623465623038336666366333313064393733646136613637633733646635663664 +66383966336661663635616162303261323531393238633039623066643961616333323165396237 +35373238623066626262616361356239663634303235643733343732393035333366306465623938 +32363932643064383732323161353338396136646430666663373039383462613034363238663737 +64636230366164383338643433643934346463613861393339666139663438396264623965313532 +34313738656665333463346165643230643738323265386562366364333039326538663461393030 +63333339336431633937313137376332333539623632653935613632386435313135376232616530 +36343537643930396539383633343434656366323664313638333363396663313362663038366538 +64663632666437643139646461653038313633313933373763366332366239353938326631346562 +62316239303962616162366139373262396535306634613966313433626331666565623339633935 +36316139633530396131373337323665616465393862373135343831313362393535643631643963 +31626164663366656337643334333132623431613038666532316161366435633462663061333961 +32383366313032616230636165323064313162306236393031393831653337646662383864363765 +31646337393135656465353539653537613166346264373663303539616664623566373637386462 +39316265333332353731363233303935636438313935323064626461663464363332646236616633 +36663664653166343461333830366435393036363466346235316334313464643037313933643938 +38643961616634316137626136373462633865663633353233323030383535623466666166656463 +34643164666536643731356135636264313765326334353639313531616665643831643831316633 +63613237616337656231303563373338363866633137346263353231346466353733393463353931 +66323336626236363735393232356634396161623438373530653436333633373065393634343436 +37313565303661616539623264326333316262373061653162623135346361653963626339393736 +31373238656161633461613733323334316633303830376363613934623731663664633065386162 +35316263613463646162653239653964613963613236623139653161386334353430373637363035 +31643937666230646237376435376361646331393662383939646138393735323861633332366566 +35383930666434366137386166646261343662303533613833333139633961666466366663663736 +65633664363530336534306138326230343265616231356565386235363534336530383032343433 +32616333363130393964363534643365346162663236316365636130303962323230613265386335 +31653931656162323630356331323861343632623364373263316534623539653663663361616363 +65393261613236613565333332316262306638633231633363386639363430303133316233616230 +64366162656531326362616537306536616363353861616437633866333830373761653064393865 +30386465363831386261383830633662663336623066346237303736326530336164323161646166 +35616430373533393632636662623766623638396265326266383431646166613730613466353461 +63613236336165353433636262613631633837376639323430666337373230623531613831363531 +39356230336435333238376139633530353464373436326461376535363334383536636138623361 +61623637653138636232356531333034363265383434633662323235393065333663326431376663 +37356633613638626537336166646464306439666436346134636666373239313564326234376561 +65333539323761646562366338303430626138376462383934363930663564313130396261656464 +36326138353361633731386266373162396662306562393962613039323335616230383834313037 +30613166303765306639306133656665646431636430366361316332646137353036333238323334 +61323964636361323637326630313165383035623138616162383633353966313036616661303837 +61303632393030363334366565613565646533376337373066383833323766343939633762396261 +66616436323430656439323461616631333165353762366234653666623633316332316532353933 +30376330643432653731353966626232626336343231376231386138663563306339633132626666 +62316638343737363730373062386535656233653732383531633430636164313563666437336137 +64343538616538373665633236646461616536633663653938646534306236313536336232366232 +66333033643364353238623834623661303661316430326332616532666435303835376261376637 +34653965663765623266346263623135666537366564666464326361643861363131326437306532 +36326365313764663763623334353132386336363833646661363537303362333534323530363332 +33356362356365616164396435396236633164386634613261636634386234643437643033616662 +36653766373565623037623033343361663936376536353034613061316337306531353861613131 +38303239303465623233346164393966306134343136333864323563623263623661396163616465 +65663762303435366462376365653236323133626434336130333637376636353033636539363462 +30636663363361313132303936303764656437616662313430333334636630613662383838323331 +33616434333761613335626362626634666634313532373837623034396336383634353862396233 +34356132653037366166646132643733313131623666663534313635656562306437633032663934 +32303630383932616630636161323561336438663137383561363035386239363038663532336232 +37656431633366303530376436356362333037326434323163313963646466376662346537633738 +37653835653839353264306239343234326631326232613736313133303865636536356130633665 +32636533326661613437326634386363653130623231343566393664313430666565333764636335 +34393235386233616665346438643661626465633135623439626434306263656331363666626130 +38643939306635653061386464336435363435643832663538623238666537343438363563653738 +37616662646433316231363462393834646233323634346331343364373462633937316439666335 +63313935643637393033323462383261373061306464656232303164353264373765373365313838 +64303033306133663634636361626162323065353539643739643233323737326135616564393436 +30366538326138623364333136613063663533386433626562346365656339653261386662356130 +35636330303731346534376231613939616263653866663461393939623037363030306336376461 +35623962646232666237363561303439393064333737616434333764373465353533633035643230 +62616662623165373439306431376330663239393333393238356339623164316531356430316464 +38353262353535626633366237323030373563343561623265363236333862383765353136636264 +38613462326632396231613234316531353034316264663731656361633866653765623662356131 +32623966373337373334323438316235386663336665623861613330313039356661326236613562 +66646334326536323162383138653433376335323336326432326532653162313335643137316132 +33653261326435336536623566323261336632383130363563663035353532386566323365663335 +64393534383138653632326237373362363337353135613733323933646439653238323138666130 +61343830643830613034303130353130363332336161363037336439376433626135383530363765 +35363035663666323039326131303265663832646338616334623737626230363439313866633233 +31333931666365613662306161306365653137633565333037666363336636663435656534663131 +64323832666437386133656161343938373364383437396535633864666163643530323965336237 +63616334366339366334383466626131353639306532613935373737653565373935663638623462 +33376535613730333931326262363235393539623339313936653965346565663063613436363664 +31636236626236356439373764393262316562313933373434643536333039653432393361353762 +65363735356163353463653531616666356138613966383433363634626662646632363865626438 +62613562333563313431653236316639666638313932373731393163343063373663393263313735 +61376465393265626434303636313738613135353338613334366137356335616432303062623365 +35393439366337366261366263383532316332353537663430316134356439643266366364633735 +39363662373265616636333835353062346137366265373865653765326233623664373561653234 +36356163626364396164643135373237653438323531333331333835623463373837666564303835 +36356662313733333336626236356165643539616235633866313565366265636631346666396634 +38313163376531653063373633613163326235636564656134383365656138386236616337636233 +64366537366166663864386130326663643131356432383538356338326636363431303466316431 +31633236663135623062303030623335316634363036356538376165663634336166353264643833 +63616135343535303965623231353563303630323166363534653134613936656638653832643464 +62306338636330363535343836373537333865353838323031396638333433396137356665633663 +65353639366265323835616538653837343634356336336263356661613466333961353965363966 +38613930386263623639643130643563633136333833313834363339393637386438316266393934 +61373063626630663565313436383333373939643237396661353233626135396238626466336634 +37656432323031366634346366383032313930356638353431373863636537373438313734643236 +36323837363239383132376263666362303564653462646230616234363263396533303332373063 +31373735306261326561303435313436373539396535363936363637666137343130653130623265 +30613538343233643230353234343766666461343335373032373038396165313238626135303835 +30366364356131303431333561393033316461643464393130306637663237653731363531633964 +62376366373730306532333137316434663964363337653238386233633434393838656466376436 +66656166356137656339333230356266393564313463363264306132373464333237316438626235 +30326237346236353665396533366339653063353430383266396565376431663035383163623733 +63646363336664373530383933353961633639636465306631323538336563626638373235303365 +30636533313830333634386237333137383465313938376139373636343833303734313334633164 +36376136626431323034343661366137306565636163303232343564326232633364363031643035 +31633065656531353835346435613833333662373736386361633437616231663038663732323731 +64396232353363346134393330613064643265656334346436663062393866626432303366646234 +34636530373263333763613231376466356635626162363463343331356264363639356236303733 +63363533653233363433623661316439303138333831313539653238386434343433616533663837 +34393065633034353136666438363931306539653161616161303432376664373638646566376531 +62303734346131373666313064646532333764613237303661376330393534333162383839366135 +39616266396165353734353865306238323532633539656536313331306239663564643230623563 +61376437656536663866396666653335343063643663393066323536346563313039356431323339 +39313033386439333136393665633735663638666538343530633362313530393063386633663631 +36396636663865383334623964306332643339646334616132393030323065323763323034343731 +62376134623932343132353536613335646433333038336239343861643137386130393237633538 +30323631323866633839616136306333393366666162396239303965633830373739383533623231 +30613131623538373037343564376430666132363865393636393139373032333464646337343832 +63373230643963336439383761316662313533656133633863346637333439363831323466346631 +34386534666431313233343431623062633033313263393938373031346537616530383962383365 +34383836313134376634393538633632646339613438323938653566383038636361393332346264 +30653363326236613237656538313733303639626634303763366364373833363261396332663239 +37396364363238656436343731636234316561323661656237633165386662396536376336353136 +65376434353935366637623830626633336435373439613336653965646266316463346532343238 +65306164643734393931366439633764306336653530616536643130653536333265646536633464 +61363865383030373962333834393661303537336335343930613339666630333561356434616135 +66303339326236356161343136653665613461343261366639383839633331376261386630396164 +31663230363763326132353261623735613463656231663439306565353064303363313666613666 +61376333396564376635643630313332623634636132653637333563313364383037343135373033 +65656435306133383533356661363832633639353734353133626330356539306164643030366466 +39326531343031643834363662333631626439343830626265303764663132626166356530356563 +39643334613339653630663661373639353739316464386665616666636337336233306632376563 +33656337616638383532323063663361633636656361626630343361656334303431616238626630 +31353766323839653562323838363439313131383164356134343436653361643964373730333632 +65366232363462383330333435646433636566356130346631323661336333396134323130363464 +34383164386138366433633961343965393137643230396337626133326633626330613038643938 +39666530383733306332363632363930393065613865626638373063343865363065386431373166 +33656233353731346132616135326433666362323764373965643139633739393436326239313564 +38643462343632633661396339346536663963636339363331393063633665363032366163313030 +38323631646366366637316233633064663434306164616530666466623233346138346136656239 +31316331616238393232396131633538393432373336613937373261616135356133626330353566 +63613235623239386434306637646262646535623134313966633336646237613664353134656537 +63613362373365646334336333633662653830626462363361623764386137656130386661373335 +39333065393363353663353564333933386236623061653264396163646330376137656232376635 +36376130376434346366656361383335383033393066653335353236316435373864393632663066 +64666538663064333664336636346538393438656531323039333761623533376565633231346466 +30633334333730303266636530613637666236653736623366383635643065663335396133613131 +65613037303832326635326435343435353964653536383537646262653731393730363466343532 +63333462353937326637353436613232356264643436626637663164663263353037336166616336 +32653438316462383234663661656634363735366661643233653534393862303833316133333535 +61663965656538343834303235346533633930626131633766346634323434626266316235393039 +34373039376137663261666435323631663833353238366635386134626538303231396132663938 +62303064323236653533366662336338396435353265393930396665633936363430383133613131 +32666665336434306165393833663331333637656531653032633461313533323239323362666666 +38333338646262393361346230363335393231616631316337313134356635646461316138306631 +61623265656162303932633532646436613839663337316637626463343539626563636663363464 +65663437353563383164386332616236343934613364313239656161623035313131303464666463 +34663961323265383932313965333533616364326232396139393261303333616435643665353339 +61346166386232336633656635613562393433656161616339623461366163333738353263343462 +64303035353530613934363562636634656630306166373537303961616561383261346339623931 +62326364646531313536326533376638353761386231663065613231333339353235306233336133 +39346636353533623562356339646234616434356331383632643762343831323832306261346438 +61366436616432626432613939383565656233306432393061373465353861323863343163343438 +64616439636163333262616665343731343936386537343163326137663332316432333333626430 +39616463626137343638626466303065613966373234373830356566383331653961363734646630 +64653234393336396561313730323361306636653139393562616361336538393066343133396566 +61366437383933663165366436336432353639373136363430623865343332333265333261363861 +62393332613664393762393737306630353239356238366639663164373335666630363335663334 +65323066636365626132653630363332303837306261643432323666393339363864626463383031 +37633536323336666364313136636664373137343464643934633233666230636432313935643135 +36353631373663373237656130646363613231383966393333376362356464323162643632326564 +35636530393731316635346464333863383633363833373431646663393666316239623736346463 +39363864646366633632633461663332376265376239313438306565383338363961663536346663 +37323634633235353738643662396163306664366465383934303765643732303439343133653663 +35356139336564643331653730313239623064646633383839356139653436636332316533383565 +38633262316664363664323064376461663430386434326664373134303964373934343630326635 +31653136316631653063346138333361343661393837333735613030626464333930393832393632 +62373361303134343639626237646232666536643063303962656330623834366336643863313163 +61653937376136633539363164326534306131363162653537366236343430373065383136313331 +62303433303662613161646233366566353365313433363030303562383336306137313338323962 +30633663393061373264303032373639386163383733656164656432626331333161373365663765 +39363836316333373238353038346466363739633338383333666564306364613439353361373738 +38393035396637626330623762376431666333393966396537373532633762373666633037366361 +31663334396534636631616333353539626236376535636263393265353135373534323939336539 +33323038376662626663373630366264613334353932343739343331336630353266373762656631 +36633162373461356437323835303061613937323739623935336532643238613966653163363038 +30363338326439633933663631326265333261396565373962353832346266393533303330666636 +35326637333864313233353364366562613563663563373638383230363639643261623338616264 +31623462623736303834333363376632343930633437616136396363363938653465306564633437 +34613036626331366431326263653334623964343037656634616539656635633961643136343230 +34633732386535313930616238313865366239396163356232346136363639393062373730663362 +31396635666632373861303931386530623533393839346166346130363266376133306666633839 +30396638313335616131353433343962363038366536383737326435633730306236346233373430 +37333165653264303334386566343234643737343539616365356361353038313037323933613139 +61626238326330333739633535386566613932303061316636386263633439373432363637396539 +38656537383565653232323663613832333563633736383262316362316234343631653035633537 +63363434333934663336396166396161313164306239373337303637663531656638373036393133 +30656166306462386536376436653162306330353661363337663762383432613663613836393232 +30333831613136356434653637643130376163643537393163633666666239396330396138306538 +37333936613062346666346532353330343633323236356562376362663631333130326263356137 +36663138346664386432666439353666323831323664373361653638373539646338633861373235 +62653139643130333936316332323763636233336666663164303133653162323734323862343630 +31393831376164663862613864343963623432633839653563643138623563336365363932653466 +39636162643033373761376262643537336261306436386661653165343532336663373266323339 +38636663306139366365643937386537633562653236343065323061353439346332663964636365 +30643333383465623636313838623733353265636637656432393839316561646165373162343235 +38383637663532666565613632383636613630366130386433356233653464393836336535316533 +62653866356165636666333035303538363161373232316130623039623365356566383037313130 +31663861373834383633346230366632663866396431303831333065333731366639656430346339 +34646433373763643064343566663832666464346332366336323033633464656630636164386233 +33633164363265623865626532323232363536386438373334366636393131313364316162613766 +62336436613332646331326433663464336565323534376662646339393734633032633163333037 +64343731323363396230333534643062353137616234623931656234643964656237393930356661 +37323238333061646265306264633535626363336636313938333236626539663361326633326536 +36363534356430663831653039633263373233376636653961663037326636373332343464313739 +35643837396230323461616630323363343464326131313832336361643164326235363964356364 +38373535356538313437343630303633386235393137373736663363386562383334633061303334 +35393563663637353662306162396666663230353661373633383730356663363736633237336161 +31633831343237316163363731616565323065373062653166323430613636303238303936313036 +39353933646332306334343931373533333564623437623137633732313562333162666338653732 +34336133396532663663336231356635613533363664646234613339333365636565626231383839 +31323161383365663634346265353234333831643665363236383466623561346563383530646364 +63623266623236356165343738323539306136366438646336366265616163353062616635663639 +38616462313366343961303631626539626631363162613039316265303338356162626335366134 +36366332373161353764343338363634373637643661323834656266376530646434373062383137 +61323831646535393934306330323533636437393233346162336339613362366134383738306637 +66626337343263353938323462316561313338363062376466633938313864616262616533386163 +39616135653538656464353363306237636636343965313165393263373265376465663661323462 +32666531613831326461656234366364356230353637616435386135323534643465653134393363 +36366665633230333232643532396137393861373563633736323237653164373763346138373232 +61656335326134663338613535316164373539396234343539313466373166656332663664373132 +30613337366430323663323339306437353262343036643135373866616366383235626562633633 +31366362323733313438313838333832613635643036336539336634303961346135306666343032 +62316462363262616663306264393237346133616239376332306337363164303639326139633232 +65383038366437376430626463633632383830653839363365323231393264333436316461336430 +36663236336364663962373535646461393838626336366439646134613138623465666534393631 +63376336336237303636313533376138326666643964643831613764326233313762326639643131 +66336234343562346166323630633336623839306563623039626361356662376139303531303466 +63633334636636396466646633326464613232326366393763346361313338306465376530313964 +65623330353161393130633364313530326537393139346231383833656465623435333438363331 +62363863653938343462613437326133616230393762643162343937336663373763306266326664 +33316133353638336364626331633331393234656533333065656637383930386361373665326131 +61303230613236366333356537383138633537353261333730636463313034396465343863346630 +62636131373361393231343532316238393762633338663132656663343237393734653230363438 +36633433373266626165313030316665343837316431666562353838303732333535313763306361 +65303236653331313734663663303535633361626530623935653763303536356637623131386531 +34613033313365373863306637656533356337393061313265333436316333636230343631336462 +32323238643261336162323533633935663962663363633539313165656461643835666438356638 +38363436353561336663386162666464616535303162333962316566353333663161323966306366 +30653532656566336334343336323732353539343139623638626130623730356138333762343236 +31636332616261353263373562376536366234646438323533313133613938356561646639376237 +33346530326330343862336535343334646538333839333630303265343164633164333931613663 +30343037356434306330363162386465393265343634333464323738313962643963623539353836 +61663130393837396535396135396164373161396363313362616364316466363230663661613138 +35386463343164623865646365373162613331333033663730346266633139346237373134326236 +62343666396330343963643332366530633136346434623665616239393461346134343562323865 +63353135666634353438393764383666633437393032393439343638336230333762346365613062 +63333130633637376231373530663839306364306161336233653632386165343865396633643962 +61336333346631316537383335643437646631346337373134383934373363366535376462376133 +31653439343764636238333932313930386265643734653934386232613461396366366561343835 +30626538353061303330303338646438333038383436636464363935303565313762633034363139 +30303735653265336238373862356631643238376634323065656263393262313739393963333033 +38373036346332323237363939613738643364333435653031363464633261316636663639323237 +33326461643864363062616538346161643263623166626534303165333161656165343963363363 +37343763646361326566633736356438356530313932643132646466313431366130626234346439 +36643433383438646132373563623736383738333538373162323865376261373639353366353462 +66343037643061393237373464356639323730376530383363623238366437613664383335343738 +66643364653138323834326463356437646433393265326331333334313762653133353539653939 +64613666373866356263646133303362316461323430303862666436326533636165333535313034 +63343533633234383764303833613837623061353363663430663339653339336137633561633133 +64633261386130326365326232343732643030373064663161336330323862643631616533623635 +61613934313565353561343961386663663466373135383530303535646333633862303630336230 +62656138656361353562383035616266666138383739636665633534663561343039356562316361 +30376437666638633131313538303132663031306638636165636435613233303538393063643062 +34316161666539643964376361383534306434303231303639636630663966376361313337623430 +62326531313138346431376230313665623530656636333332623565363835363261336535663366 +37623364373766643631666638373238353930363261353162383633373732353535346333306335 +34353934373836343733386133313037656430326236356633643263383233373638653337303036 +34366432326130333263636638356530333831343361643437636536646536373662316263383530 +38393436626530633831313064626664393537653364336266336539306536316635303532363136 +61316462653361383631653064393966363631303334336433343962643764363763373566343166 +31653737316234313963303234386432656164396164373863356265383962383839636639383739 +38396134383430353730626164373666326163353434386466303565656331313764653230356561 +63346662636639396662333732643165386630393630393431613036663330303238313234656565 +36326133323865333230623738336166326239626361613637326434333935626664643765323030 +32613961666138356463343931303132303831353962313564323162343737386134336561666632 +35333531653331643232306532653430643362653034376631353333326531663966333963656231 +30346435653666326664356531643433383963396365366633616534663336316265363563613137 +37653364343131306432653435313635316661333561353038666433363861353936383830393530 +30633034356631356561386233366138383838666463303438363732363335646133323331366161 +66333433383637373436653638656234356466396330613066633039313931626661353330353839 +65343539356330633165383132386231303131323231363865326663363138373761393337323935 +65323236336365633265343930363132343836373366636539353865363134663337386161613236 +39323338323163646337663663353331376536303330623265396562616362643465346164373232 +34623061373266633234346237333062366537356562636265383730303636326137343965313161 +34386465396465343731613233333965373761313639613236666166353035613531303432306336 +38313432363038666635396239373734393235646139323736613435626166613166653835623165 +31376230633232616333306361343066383034663962636631623462316666333135343466663430 +32656439626636366332653230333337623132343864336430353964626335323862316339313063 +38336533633830303866346639626234343462616461646234346464623962666631303666326466 +33313738636362383135323031643263333031663135393933303035623333393232616464333662 +65396432653764373766363938393731343835376561313563396239646565616135376663306164 +34366537373864326533396666383738393364353438623161613833663465613535653561366637 +64363862323362616531616131653331646664393265613738396666393732643966373634313264 +66633436376130356466623436613036363936363931633361656162356533633961363531333662 +65316463623663326135323338393166613162306535353437356632383337616431393033636439 +63623336363562613332323235636634326539306634343966326237356363356331666433333862 +37333332323665303032633661373432623430643733376137643638353166313231313565623239 +3366 diff --git a/.talismanrc b/.talismanrc index 4fa760d454..4a1d2104ba 100644 --- a/.talismanrc +++ b/.talismanrc @@ -8,7 +8,7 @@ fileignoreconfig: - filename: .bin/scripts/set-cypress-env.sh checksum: 4463ed7c1d5b82a8b152248b953778f37771bfba72865ee0e8af3b61cf3c38da - filename: .bin/scripts/setup-local-env.sh - checksum: f3cd7443153a8d4bc742ea6075b2ea9a174572b736186c6759fbf29f59567fd8 + checksum: 164cfbaa5965f9c06f84d90cb7e5af0df0c4cc1745e57d99490d44ba6efc1b33 - filename: .github/workflows/cypress.yml checksum: 39f98fb68fdebf6a36959706adb43a8219a4b7781ac35329f957dc1cfa8b6de0 - filename: .github/workflows/deploy_preview.yml @@ -24,19 +24,17 @@ fileignoreconfig: - filename: .infra/files/configs/mongodb/seed.gpg checksum: 646eab49f6ff33a2d4d2dc9892ae14ca7871404c81459fc4832b1fb12abbe1c9 - filename: .infra/files/scripts/seed.sh - checksum: ddafc86248e8fd5f7c24ca5a62be703083f7704395f17fb7b43bc8e44227d561 + checksum: 95122f596aaf41a82615adc5e6a824a25e123d3b3a5aef1e424405a10c1e6429 - filename: .infra/local/mongod.conf checksum: bb2ce0c27102259a5fa39da1fb4460af9ad6ad58adc715312e53dcd69c8e6be7 - filename: .infra/vault/vault.yml - checksum: 03ce5ac0cec24a0ab82c323635d5f1cc53878f3f1155631c2998006340768069 + checksum: 0e6ed4fcfb4379235d2731a1f343e87d5f60bc76d698209c9897267f58ea0b81 - filename: cypress/pages/FlowAdminPage.ts checksum: cbb0a8651ca4c5d807f03eeeba6204c7d6d3a5f17ffb0734921f18d54f99f6b0 - filename: docker-compose.yml checksum: 8cdd1da6c1155f26b417a27e26311d4f00b7d8bd6c21f1f86c1c7cb3f0599e6a - filename: server/.env.test checksum: fa62b8d2d46d35ff56ebea647e4762551b91780b1e115612cae7e4bda3f56764 -- filename: server/src/common/model/schema/_shared/mongoose-paginate.ts - checksum: b6762a7cb5df9bbee1f0ce893827f0991ad01514f7122a848b3b5d49b620f238 - filename: server/src/common/utils/awsUtils.ts checksum: 0acc085847288b9f2d5235f118e29199a168b368c33a7e37ab7dfc7e143fb507 - filename: server/src/config.ts @@ -51,10 +49,14 @@ fileignoreconfig: checksum: d2770daa97ae332eec0b66497fdb717229895583ac3bfd48af1a830b36504968 - filename: server/src/http/routes/auth/password.controller.ts checksum: 0eb3948d875508edf6d31f0ffe1290aac0cc02c9c80c913bcb04a312edd062cc +- filename: server/src/http/sentry.ts + checksum: efa665e02ca4d3acbf48c5dc549dae4e915c02ae0626bedf71e3608f8d5e5ebd - filename: server/src/jobs/database/obfuscateCollections.ts - checksum: df959adedd069bbfd68c6c5c99a9f506b980147a973f95b517c24e740d79ee37 + checksum: b2187fd541ab53581f3313f43dc9aa60dabce658ae848e63b9a85c2e42a953fd - filename: server/src/jobs/job.actions.ts - checksum: d716e214d828109181a138f0ae253d5489a3c544b2625917b458d1e07886c408 + checksum: 4db1a4c6047165e8032efd563cf594e6169b7065e04f1333df22ddad56343431 +- filename: server/src/jobs/lba_recruteur/api/createApiUser.ts + checksum: 8e4712bae8747c1f0f2ba8b4ac3f3af118772136c16b6318b14a2d8b7e277dc6 - filename: server/src/jobs/lba_recruteur/formulaire/misc/removeVersionKeyFromRecruiters.ts checksum: 3cd111d8c109cfec357bae48af70d0cf5644d02cd2c4b9afc5b8aa07bccbd535 - filename: server/src/security/accessTokenService.ts @@ -92,7 +94,7 @@ fileignoreconfig: - filename: shared/helpers/generateUri.ts checksum: 6542db0d3eca959c6e81d574f8b71d4b18d2f1af21042ca5ed4dff319cd39555 - filename: shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap - checksum: acfade647afc6a09dc05fe116850ca4b5e9ce9564fdc74015436748b4001bc09 + checksum: caa1131ffe2f23d62ba2d4370173cce74ffa05a17330c8d342c41c4b971c6f9f - filename: shared/helpers/openapi/generateOpenapi.test.ts checksum: d7b85c3dff488cec523d78f0926e15dbea41071a1864bda62b4d6caeb2541df3 - filename: shared/models/applications.model.ts @@ -149,6 +151,8 @@ fileignoreconfig: checksum: 1ad48425b890a5ed3de19d079692e2ef7eac76483339a469a6cd9bc6d796ad26 - filename: ui/utils/api.utils.ts checksum: 324cd501354cfff65447c2599c4cc8966aa8aac30dda7854623dd6f7f7b0d34e +- filename: server/src/services/referrers.service.ts + checksum: 966b0ece2b18b5a6066df531524c97ba0ad38266e782a334004e8c127b41ade6 - filename: server/src/common/utils/awsUtils.ts checksum: 0acc085847288b9f2d5235f118e29199a168b368c33a7e37ab7dfc7e143fb507 - filename: .github/workflows/_build.yml diff --git a/package.json b/package.json index dffe59586e..e040e85e07 100644 --- a/package.json +++ b/package.json @@ -73,32 +73,33 @@ "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", "@types/clamscan": "^2.0.8", - "@types/node": "20.7.1", - "@typescript-eslint/eslint-plugin": "^6.7.2", - "@typescript-eslint/parser": "^6.7.2", + "@types/node": "^20.12.12", + "@typescript-eslint/eslint-plugin": "^7.9.0", + "@typescript-eslint/parser": "^7.9.0", "cross-env": "^7.0.3", "cypress": "^13.6.4", "cypress-slow-down": "^1.3.1", "dotenv": "^16.1.4", - "eslint": "^8.49.0", - "eslint-config-next": "^13.4.19", + "eslint": "^8.57.0", + "eslint-config-next": "^13.5.6", "eslint-config-prettier": "^9.0.0", - "eslint-import-resolver-typescript": "^3.6.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-import": "^2.28.1", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-n": "^16.1.0", - "eslint-plugin-simple-import-sort": "^10.0.0", - "eslint-plugin-unused-imports": "^3.0.0", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-simple-import-sort": "^12.1.0", + "eslint-plugin-unused-imports": "^3.2.0", "lint-staged": "^14.0.1", "node-talisman": "^1.29.10", "prettier": "^3.0.3", "semantic-release": "^21.1.1", "semantic-release-slack-bot": "^4.0.2", "ts-node": "^10.9.1", - "typescript": "^5.2.2", - "vite-tsconfig-paths": "^4.2.1", - "vitest": "^1.4.0" + "typescript": "^5.4.5", + "vite-tsconfig-paths": "^4.3.2", + "vitest": "^1.6.0" }, "commitlint": { "extends": [ @@ -119,6 +120,9 @@ ], "*": [ "prettier --write -u" + ], + "yarn.lock": [ + "yarn dedupe" ] }, "resolutions": { diff --git a/server/.eslintrc.cjs b/server/.eslintrc.cjs index f8b171116c..593f97b50c 100644 --- a/server/.eslintrc.cjs +++ b/server/.eslintrc.cjs @@ -5,6 +5,7 @@ module.exports = { "n/no-missing-import": 0, "import/no-extraneous-dependencies": 0, "n/no-extraneous-import": 0, + "import/no-unresolved": 0, }, env: { es2022: true, diff --git a/server/package.json b/server/package.json index 10674c8cd5..e5c7745c0a 100644 --- a/server/package.json +++ b/server/package.json @@ -37,6 +37,7 @@ "axios-cache-interceptor": "^1.3.2", "basic-ftp": "^5.0.3", "boom": "^7.3.0", + "bson": "^6.7.0", "bunyan": "^1.8.15", "bunyan-slack": "^0.0.10", "burner-email-providers": "^1.0.67", @@ -71,8 +72,7 @@ "migrate-mongo": "^11.0.0", "miniget": "^4.2.3", "mjml": "^4.14.1", - "mongodb": "^3.7.4", - "mongoose": "^5.13.20", + "mongodb": "^6.7.0", "netmask": "^2.0.2", "nodemailer": "^6.9.5", "nodemailer-html-to-text": "^3.2.0", @@ -89,7 +89,8 @@ "type-fest": "^4.18.2", "xlsx": "^0.18.5", "xml2js": "^0.6.2", - "zod": "3.21.4" + "zod": "3.23.8", + "zod-mongodb-schema": "^1.0.2" }, "devDependencies": { "@sentry/types": "^7.72.0", @@ -108,7 +109,7 @@ "eslint": "^8.50.0", "supertest": "^6.3.3", "tsup": "^7.2.0", - "typescript": "^5.2.2", + "typescript": "^5.4.5", "zod-fixture": "^2.5.0" }, "files": [ diff --git a/server/src/commands.ts b/server/src/commands.ts index 7b1f6ed3d8..29efb55576 100644 --- a/server/src/commands.ts +++ b/server/src/commands.ts @@ -2,11 +2,10 @@ import { captureException } from "@sentry/node" import { program } from "commander" import HttpTerminator from "lil-http-terminator" -import { closeMongoConnection } from "@/common/mongodb" - import { closeMemoryCache } from "./common/apis/client" import { logger } from "./common/logger" import { sleep } from "./common/utils/asyncUtils" +import { closeMongodbConnection } from "./common/utils/mongodbUtils" import { notifyToSlack } from "./common/utils/slackUtils" import config from "./config" import { closeSentry, initSentryProcessor } from "./http/sentry" @@ -70,7 +69,7 @@ program logger.info(`Starting command ${command}`) }) .hook("postAction", async () => { - await Promise.all([closeMongoConnection(), closeMemoryCache()]) + await Promise.all([closeMongodbConnection(), closeMemoryCache()]) await closeSentry() setTimeout(async () => { @@ -164,6 +163,7 @@ function createJobAction(name) { } } +program.command("recreate:indexes").description("Recreate MongoDB indexes").option("-q, --queued", "Run job asynchronously", false).action(createJobAction("recreate:indexes")) program.command("db:validate").description("Validate Documents").option("-q, --queued", "Run job asynchronously", false).action(createJobAction("db:validate")) program @@ -185,11 +185,6 @@ program .description("Fix duplicated users in users collections and update appointment collection accordingly") .action(createJobAction("fix:duplicate:users")) -program - .command("migration:correctionRDVA") - .description("Corrige les erreurs de données ne correspondant pas aux modèles associés") - .action(createJobAction("migration:correctionRDVA")) - program.command("db:obfuscate").description("Pseudonymisation des documents").option("-q, --queued", "Run job asynchronously", false).action(createJobAction("db:obfuscate")) program.command("recruiters:delegations").description("Resend delegation email for all jobs created on November 2023").action(createJobAction("recruiters:delegations")) @@ -218,11 +213,6 @@ program .option("-q, --queued", "Run job asynchronously", false) .action(createJobAction("recruiters:get-missing-address-detail")) -program - .command("import:ficheromev4") - .description("import fiches métiers rome v4 (pas utilisé 29/04/2024)") - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("import:ficheromev4")) program .command("import:referentielrome") .description("import référentiel rome v4 from XML") @@ -243,12 +233,6 @@ program .option("-q, --queued", "Run job asynchronously", false) .action(createJobAction("migration:remove-delegated-from-jobs")) -program - .command("mongodb:indexes:create") - .description("Creation des indexes mongo") - .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("mongodb:indexes:create")) - /********************/ program @@ -555,13 +539,6 @@ program .option("-parallelism, [parallelism]", "Number of threads", "10") .action(createJobAction("referentiel-opco:constructys:import")) -program - .command("resend-prdv-emails") - .description("Renvoie les emails de prises de rendez-vous") - .option("-q, --queued", "Run job asynchronously", false) - .requiredOption("--from-date , [fromDate]", "format DD-MM-YYYY. Date depuis laquelle les prises de rendez-vous sont renvoyéees") - .action(createJobAction("prdv:emails:resend")) - export async function startCLI() { await program.parseAsync(process.argv) } diff --git a/server/src/common/apis/FranceTravail.ts b/server/src/common/apis/FranceTravail.ts index 29c6ba2e59..8f037fd883 100644 --- a/server/src/common/apis/FranceTravail.ts +++ b/server/src/common/apis/FranceTravail.ts @@ -4,11 +4,10 @@ import querystring from "querystring" import Boom from "boom" import FormData from "form-data" import { TDayjs } from "shared/helpers/dayjs" -import { IFicheRome } from "shared/models" import config from "@/config" import { FTResponse } from "@/services/ftjob.service.types" -import { IAppelattionDetailsFromAPI, IRomeDetailsFromAPI, IRomeV4Short, ZFTApiToken } from "@/services/rome.service.types" +import { IAppelattionDetailsFromAPI, IRomeDetailsFromAPI, ZFTApiToken } from "@/services/rome.service.types" import dayjs from "../../services/dayjs.service" import { logger } from "../logger" @@ -204,38 +203,6 @@ export const getAppellationDetailsFromAPI = async (appellationCode: string): Pro } } -export const getRomeV4DetailsFromFT = async (romeCode: string): Promise => { - const { token } = await getFtAccessToken("ROMEV4") - - try { - const { data } = await axiosClient.get(`${config.franceTravailIO.baseUrl}/rome-metiers/v1/metiers/metier/${romeCode}`, { - headers: { - Authorization: `Bearer ${token}`, - }, - }) - - return data - } catch (error: any) { - sentryCaptureException(error, { extra: { responseData: error.response?.data } }) - return null - } -} - -export const getRomeV4ListFromFT = async (): Promise => { - const { token } = await getFtAccessToken("ROMEV4") - try { - const { data } = await axiosClient.get(`${config.franceTravailIO.baseUrl}/rome-metiers/v1/metiers/metier?champs=code`, { - headers: { - Authorization: `Bearer ${token}`, - }, - }) - return data - } catch (error: any) { - sentryCaptureException(error, { extra: { responseData: error.response?.data } }) - return null - } -} - /** * Sends CSV file to France Travail API through a "form data". */ diff --git a/server/src/common/model/constants/appointments.ts b/server/src/common/model/constants/appointments.ts deleted file mode 100644 index f56b00d071..0000000000 --- a/server/src/common/model/constants/appointments.ts +++ /dev/null @@ -1,12 +0,0 @@ -const mailType = { - CANDIDAT_HAVE_YOU_BEEN_CONTACTED: "CANDIDAT_HAVE_YOU_BEEN_CONTACTED", - CFA_REMINDER_RESEND_APPOINTMENT: "CFA_REMINDER_RESEND_APPOINTMENT", - CANDIDAT_APPOINTMENT: "CANDIDAT_APPOINTMENT", -} - -const candidatFollowUpType = { - CONFIRM: "CONFIRM", - RESEND: "RESEND", -} - -export { mailType, candidatFollowUpType } diff --git a/server/src/common/model/constants/etablissement.ts b/server/src/common/model/constants/etablissement.ts deleted file mode 100644 index b87abd730f..0000000000 --- a/server/src/common/model/constants/etablissement.ts +++ /dev/null @@ -1,27 +0,0 @@ -const optMode = { - OPT_IN: "OPT_IN", - OPT_OUT: "OPT_OUT", -} - -const mailType = { - // Opt-out - OPT_OUT_INVITE: "OPT_OUT_INVITE", - OPT_OUT_UNSUBSCRIPTION_CONFIRMATION: "OPT_OUT_UNSUBSCRIPTION_CONFIRMATION", - OPT_OUT_STARTING: "OPT_OUT_STARTING", - // Premium Parcoursup - PREMIUM_INVITE: "PREMIUM_INVITE", - PREMIUM_INVITE_ONE_SHOT_2023: "PREMIUM_INVITE_ONE_SHOT_2023", - PREMIUM_INVITE_FOLLOW_UP: "PREMIUM_INVITE_FOLLOW_UP", - PREMIUM_ACTIVATED_REMINDER: "PREMIUM_ACTIVATED_REMINDER", - PREMIUM_REFUSED: "PREMIUM_REFUSED", - PREMIUM_STARTING: "PREMIUM_STARTING", - // Premium Affelnet - PREMIUM_AFFELNET_INVITE: "PREMIUM_AFFELNET_INVITE", - PREMIUM_AFFELNET_INVITE_ONE_SHOT_2023: "PREMIUM_AFFELNET_INVITE_ONE_SHOT_2023", - PREMIUM_AFFELNET_INVITE_FOLLOW_UP: "PREMIUM_AFFELNET_INVITE_FOLLOW_UP", - PREMIUM_AFFELNET_ACTIVATED_REMINDER: "PREMIUM_AFFELNET_ACTIVATED_REMINDER", - PREMIUM_AFFELNET_REFUSED: "PREMIUM_AFFELNET_REFUSED", - PREMIUM_AFFELNET_STARTING: "PREMIUM_AFFELNET_STARTING", -} - -export { optMode, mailType } diff --git a/server/src/common/model/constants/referrers.ts b/server/src/common/model/constants/referrers.ts deleted file mode 100644 index 38a35332d4..0000000000 --- a/server/src/common/model/constants/referrers.ts +++ /dev/null @@ -1,78 +0,0 @@ -import Boom from "boom" - -export type ReferrerObject = { - code: number - name: string - full_name: string - url: string -} - -// Referrer configurations -const referrers = { - PARCOURSUP: { - code: 1, - name: "PARCOURSUP", - full_name: "Parcoursup", - url: "https://www.parcoursup.fr", - }, - LBA: { - code: 2, - name: "LBA", - full_name: "La bonne alternance", - url: "https://labonnealternance.apprentissage.beta.gouv.fr", - }, - ONISEP: { - code: 4, - name: "ONISEP", - full_name: "ONISEP", - url: "https://www.onisep.fr", - }, - JEUNE_1_SOLUTION: { - code: 5, - name: "JEUNE_1_SOLUTION", - full_name: "1 jeune 1 solution", - url: "https://www.1jeune1solution.gouv.fr", - }, - AFFELNET: { - code: 6, - name: "AFFELNET", - full_name: "Affelnet", - url: "https://affectation3e.phm.education.gouv.fr/pna-public", - }, -} - -function isReferrer(name: string): name is keyof typeof referrers { - return Object.keys(referrers).includes(name) -} - -/** - * @description Returns referrer from it's key. - * @param {string} name - * @returns {{code: {Number}, name: {String}, fullName: {String}, url: {String}}} - */ -function getReferrerByKeyName(name: string | null | undefined): ReferrerObject { - if (!name) throw Boom.badRequest("Referrer introuvable.") - const upperName = name.toUpperCase() - if (!isReferrer(upperName)) { - throw Boom.badRequest("Referrer introuvable.") - } - const referrerFound = referrers[upperName] - return referrerFound -} - -/** - * @description Returns referrer from it's identifier. - * @param {string|number} id - * @returns {{code: {Number}, name: {String}, fullName: {String}, url: {String}}} - */ -function getReferrerById(id) { - const referrer = Object.values(referrers).find((referrer) => referrer.code.toString() === id.toString()) - - if (!referrer) { - throw new Error(`Unknown "${id}" referrer code.`) - } - - return referrer -} - -export { getReferrerById, getReferrerByKeyName, referrers } diff --git a/server/src/common/model/index.ts b/server/src/common/model/index.ts deleted file mode 100644 index 1aad0d20c5..0000000000 --- a/server/src/common/model/index.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { captureException } from "@sentry/node" - -import { db, mongooseInstance } from "@/common/mongodb" - -import { logger } from "../logger" - -import AnonymizedUser from "./schema/anonymizedUsers/anonymizedUsers.schema" -import ApiCalls from "./schema/apiCall/apiCall.schema" -import AnonymizedApplication from "./schema/application/anonymizedApplications.schema" -import Application from "./schema/application/applications.schema" -import AppointmentDetailed from "./schema/appointmentDetailed/appointmentDetailed.schema" -import Appointment from "./schema/appointments/appointment.schema" -import Credential from "./schema/credentials/credential.schema" -import CustomEmailETFA from "./schema/customEmailETFA/customEmailETFA.schema" -import DiplomesMetiers from "./schema/diplomesmetiers/diplomesmetiers.schema" -import DomainesMetiers from "./schema/domainesmetiers/domainesmetiers.schema" -import EligibleTrainingsForAppointment from "./schema/eligibleTrainingsForAppointment/eligibleTrainingsForAppointment.schema" -import eligibleTrainingsForAppointmentHistory from "./schema/eligibleTrainingsForAppointmentsHistory/eligibleTrainingsForAppointmentHistory.schema" -import EmailBlacklist from "./schema/emailBlacklist/emailBlacklist.schema" -import Etablissement from "./schema/etablissements/etablissement.schema" -import FicheMetierRomeV4 from "./schema/ficheRomeV4/ficheRomeV4" -import FormationCatalogue from "./schema/formationCatalogue/formationCatalogue.schema" -import GeoLocation from "./schema/geolocation/geolocation.schema" -import InternalJobs from "./schema/internalJobs/internalJobs.schema" -import Job from "./schema/jobs/jobs.schema" -import LbaCompany from "./schema/lbaCompany/lbaCompany.schema" -import LbaCompanyLegacy from "./schema/lbaCompanylegacy/lbaCompanyLegacy.schema" -import { Cfa } from "./schema/multiCompte/cfa.schema" -import { Entreprise } from "./schema/multiCompte/entreprise.schema" -import { RoleManagement } from "./schema/multiCompte/roleManagement.schema" -import { UserWithAccount } from "./schema/multiCompte/userWithAccount.schema" -import Opco from "./schema/opco/opco.schema" -import Optout from "./schema/optout/optout.schema" -import Recruiter from "./schema/recruiter/recruiter.schema" -import RecruteurLbaUpdateEvent from "./schema/recruteurLbaUpdateEvent/recruteurLbaUpdateEvent.schema" -import ReferentielOnisep from "./schema/referentielOnisep/referentielOnisep.schema" -import ReferentielOpco from "./schema/referentielOpco/referentielOpco.schema" -import ReferentielRome from "./schema/referentielRome/referentielRome" -import Session from "./schema/session/session.schema" -import SiretDiffusibleStatus from "./schema/siretDiffusibleStatusSchema/siretDiffusibleStatusSchema.schema" -import UnsubscribedLbaCompany from "./schema/unsubscribedLbaCompany/unsubscribedLbaCompany.schema" -import UnsubscribeOF from "./schema/unsubscribedOF/unsubscribeOF.schema" -import User from "./schema/user/user.schema" - -const createSpecialIndexes = async () => { - await db.collection("bonnesboites").createIndex({ geopoint: "2dsphere" }) - await db.collection("formationcatalogues").createIndex({ lieu_formation_geopoint: "2dsphere" }) - await db.collection("recruiters").createIndex({ geopoint: "2dsphere" }) -} - -export async function createMongoDBIndexes() { - const results = await Promise.allSettled( - mongooseInstance.modelNames().map(async (name) => { - const model = mongooseInstance.model(name) - return model.createIndexes({ background: true }).catch(async (e) => { - if (e.codeName === "IndexOptionsConflict" || e.codeName === "IndexKeySpecsConflict") { - const err = new Error(`Conflict in indexes for ${name}`, { cause: e }) - logger.error(err) - captureException(err) - await mongooseInstance.connection.collection(model.collection.name).dropIndexes() - await model.createIndexes({ background: true }) - } else { - throw e - } - }) - }) - ) - - await createSpecialIndexes() - - const errors = results.reduce((acc, r) => { - if (r.status === "rejected") { - acc.push(r.reason) - - logger.error(r.reason) - captureException(r.reason) - } - - return acc - }, [] as Error[]) - - if (errors.length > 0) { - throw new AggregateError(errors, `createMongoDBIndexes failed with ${errors.length} errors`) - } -} - -export { - AnonymizedApplication, - AnonymizedUser, - ApiCalls, - Application, - Appointment, - AppointmentDetailed, - Cfa, - Credential, - CustomEmailETFA, - DiplomesMetiers, - DomainesMetiers, - EligibleTrainingsForAppointment, - EmailBlacklist, - Entreprise, - Etablissement, - FicheMetierRomeV4, - FormationCatalogue, - GeoLocation, - InternalJobs, - Job, - LbaCompany, - LbaCompanyLegacy, - RecruteurLbaUpdateEvent, - Opco, - Optout, - Recruiter, - ReferentielOnisep, - ReferentielOpco, - ReferentielRome, - RoleManagement, - Session, - SiretDiffusibleStatus, - UnsubscribeOF, - UnsubscribedLbaCompany, - User, - UserWithAccount, - eligibleTrainingsForAppointmentHistory, -} diff --git a/server/src/common/model/schema/internalJobs/internalJobs.types.ts b/server/src/common/model/internalJobs.types.ts similarity index 63% rename from server/src/common/model/schema/internalJobs/internalJobs.types.ts rename to server/src/common/model/internalJobs.types.ts index db0562d78a..66e0ca626c 100644 --- a/server/src/common/model/schema/internalJobs/internalJobs.types.ts +++ b/server/src/common/model/internalJobs.types.ts @@ -1,7 +1,24 @@ +import { ObjectId } from "mongodb" + import { CronName } from "@/jobs/jobs" +/* + name: Le nom de la tâche + type: Type du job simple ou cron + status: Statut courant du job + sync: Si le job est synchrone + payload: La donnée liéé à la tâche + output: Les valeurs de retours du job + cron_string: standard cron string exemple: '*\/2 * * * *' + scheduled_for: Date de lancement programmée + started_at: Date de lancement + ended_at: Date de fin d'execution + updated_at: Date de mise à jour en base de données + created_at: Date d'ajout en base de données +*/ + interface IInternalJobsSimple { - _id: string + _id: ObjectId name: string type: "simple" status: "pending" | "will_start" | "running" | "finished" | "blocked" | "errored" @@ -16,7 +33,7 @@ interface IInternalJobsSimple { } interface IInternalJobsCron { - _id: string + _id: ObjectId name: CronName type: "cron" status: "pending" | "will_start" | "running" | "finished" | "blocked" | "errored" @@ -28,7 +45,7 @@ interface IInternalJobsCron { } interface IInternalJobsCronTask { - _id: string + _id: ObjectId name: CronName type: "cron_task" status: "pending" | "will_start" | "running" | "finished" | "blocked" | "errored" @@ -42,4 +59,4 @@ interface IInternalJobsCronTask { type IInternalJobs = IInternalJobsSimple | IInternalJobsCron | IInternalJobsCronTask -export type { CronName, IInternalJobs, IInternalJobsCron, IInternalJobsSimple, IInternalJobsCronTask } +export type { CronName, IInternalJobs, IInternalJobsCron, IInternalJobsCronTask, IInternalJobsSimple } diff --git a/server/src/common/model/schema/_shared/mongoose-paginate.ts b/server/src/common/model/schema/_shared/mongoose-paginate.ts deleted file mode 100644 index 067bbd1be2..0000000000 --- a/server/src/common/model/schema/_shared/mongoose-paginate.ts +++ /dev/null @@ -1,227 +0,0 @@ -/** - * The following code as been copied from https://github.com/IGLU-Agency/mongoose-paginate-ts/blob/3c574c2d61b596f86fbbe0efd54acf72df451c02 - * - * We cannot use it because our mongoose version doesn't match - * - * MIT License - * - * Copyright (c) 2020 - 2022 IGLU. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -import type { Schema, Aggregate, Model } from "mongoose" - -export class PaginationModel { - totalDocs: number | undefined - limit: number | undefined = 0 - totalPages: number | undefined - page: number | undefined - pagingCounter: number | undefined - hasPrevPage: boolean | undefined = false - hasNextPage: boolean | undefined = false - prevPage: number | undefined - nextPage: number | undefined - /** - * @deprecated - */ - hasMore: boolean | undefined = false // EQUAL TO HAS NEXT PAGE - docs: T[] = [] -} - -export interface PaginationOptions { - key?: string | undefined - query?: any | undefined - aggregate?: any | undefined - populate?: any | undefined - select?: any | undefined - sort?: any | undefined - projection?: any | undefined - forceCountFunction?: boolean | undefined - lean?: boolean | undefined - leanOptions?: any | undefined - startingAfter?: any | undefined - endingBefore?: any | undefined - limit?: any | undefined - page?: any | undefined -} - -export interface Pagination extends Model { - paginate(options?: PaginationOptions | undefined, onError?: ((e: Error) => unknown) | undefined): Promise | undefined> -} - -export function mongoosePagination(schema: Schema) { - schema.statics.paginate = async function paginate(options: PaginationOptions | undefined, onError: (e: Error) => unknown | undefined): Promise | undefined> { - //MARK: INIT - const key = options?.key ?? "_id" - const query = options?.query ?? {} - const aggregate = options?.aggregate ?? undefined - const populate = options?.populate ?? undefined - const select = options?.select ?? undefined - const sort = options?.sort ?? undefined - const projection = options?.projection ?? {} - const forceCountFunction = options?.forceCountFunction ?? false - const lean = options?.lean ?? true - const leanOptions = options?.leanOptions ?? { autopopulate: true } - const startingAfter = options?.startingAfter ?? undefined - const endingBefore = options?.endingBefore ?? undefined - //MARK: PAGING - const limit = parseInt(options?.limit, 10) > 0 ? parseInt(options?.limit, 10) : 0 - let page = 1 - let skip = 0 - if (options?.page != undefined) { - page = parseInt(options?.page, 10) - skip = (page - 1) * limit - } - let useCursor = false - if (query != undefined && (startingAfter != undefined || endingBefore != undefined)) { - useCursor = true - query[key] = {} - if (endingBefore != undefined) { - query[key] = { $lt: endingBefore } - } else { - query[key] = { $gt: startingAfter } - } - } - //MARK: COUNTING - let countPromise - if (aggregate != undefined) { - countPromise = this.aggregate(aggregate).count("count") - } else { - if (forceCountFunction == true) { - countPromise = this.count(query).exec() - } else { - countPromise = this.countDocuments(query).exec() - } - } - //MARK: QUERY - let docsPromise = [] - - let mQuery: Aggregate | any - - if (aggregate != undefined) { - mQuery = this.aggregate(aggregate) - if (select != undefined) { - mQuery = mQuery.project(select) - } - } else { - mQuery = this.find(query, projection) - if (select != undefined) { - mQuery = mQuery.select(select) - } - if (lean) { - mQuery = mQuery.lean(leanOptions) - } - if (populate != undefined) { - mQuery = mQuery.populate(populate) - } - } - - if (sort != undefined) { - mQuery = mQuery.sort(sort) - } - - if (limit > 0) { - if (useCursor) { - mQuery = mQuery.limit(limit + 1) - } else { - mQuery = mQuery.skip(skip) - mQuery = mQuery.limit(limit) - } - } - docsPromise = mQuery.exec() - //MARK: PERFORM - try { - const values = await Promise.all([countPromise, docsPromise]) - const [counts, docs] = values - let count = 0 - if (aggregate != undefined) { - if (counts != undefined && counts[0] != undefined && counts[0]["count"] != undefined) { - count = counts[0]["count"] - } - } else { - count = counts - } - const meta = new PaginationModel() - meta.totalDocs = count - if (!useCursor) { - const pages = limit > 0 ? Math.ceil(count / limit) ?? 1 : 0 - meta.limit = count - meta.totalPages = 1 - meta.page = page - meta.pagingCounter = (page - 1) * limit + 1 - meta.hasPrevPage = false - meta.hasNextPage = false - meta.prevPage = undefined - meta.nextPage = undefined - if (limit > 0) { - meta.limit = limit - meta.totalPages = pages - // Set prev page - if (page > 1) { - meta.hasPrevPage = true - meta.prevPage = page - 1 - } else if (page == 1) { - meta.prevPage = undefined - } else { - meta.prevPage = undefined - } - // Set next page - if (page < pages) { - meta.hasNextPage = true - meta.nextPage = page + 1 - } else { - meta.nextPage = undefined - } - } - if (limit == 0) { - meta.limit = 0 - meta.totalPages = undefined - meta.page = undefined - meta.pagingCounter = undefined - meta.prevPage = undefined - meta.nextPage = undefined - meta.hasPrevPage = false - meta.hasNextPage = false - } - meta.hasMore = meta.hasNextPage - } else { - meta.limit = undefined - meta.totalPages = undefined - meta.page = undefined - meta.pagingCounter = undefined - meta.hasPrevPage = undefined - const hasMore = docs.length === limit + 1 - if (hasMore) { - docs.pop() - } - meta.hasMore = hasMore - meta.hasNextPage = hasMore - meta.prevPage = undefined - meta.nextPage = undefined - } - meta.docs = docs - return meta - } catch (error) { - if (onError != undefined) { - onError(error as Error) - } - return undefined - } - } -} diff --git a/server/src/common/model/schema/anonymizedUsers/anonymizedUsers.schema.ts b/server/src/common/model/schema/anonymizedUsers/anonymizedUsers.schema.ts deleted file mode 100644 index 4ba0a952c7..0000000000 --- a/server/src/common/model/schema/anonymizedUsers/anonymizedUsers.schema.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { IAnonymizedUser } from "shared/models/anonymizedUsers.model" - -import { model, Schema } from "../../../mongodb" - -export const anonymizedUsersSchema = new Schema( - { - userId: { - type: String, - default: null, - description: "L'identifiant de l'utilisateur provenant de la collection Users", - }, - type: { - type: String, - enum: ["parent", "etudiant"], - description: "Type d'utilisateur (parent, etudiant)", - }, - role: { - type: String, - default: null, - description: "candidat | cfa | administrator", - }, - last_action_date: { - type: Date, - default: Date.now(), - description: "Date de dernière action effectuée par l'utilisateur", - }, - }, - { - versionKey: false, - } -) - -export default model("anonymized_user", anonymizedUsersSchema) diff --git a/server/src/common/model/schema/anonymizedUsers/anonymizedUsers.types.ts b/server/src/common/model/schema/anonymizedUsers/anonymizedUsers.types.ts deleted file mode 100644 index e81016a54c..0000000000 --- a/server/src/common/model/schema/anonymizedUsers/anonymizedUsers.types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IAnonymizedUser } from "shared/models/anonymizedUsers.model" - -import { model } from "../../../mongodb" - -import { anonymizedUsersSchema } from "./anonymizedUsers.schema" - -export default model("anonymized_users", anonymizedUsersSchema) diff --git a/server/src/common/model/schema/apiCall/apiCall.schema.ts b/server/src/common/model/schema/apiCall/apiCall.schema.ts deleted file mode 100644 index 1b41b517c4..0000000000 --- a/server/src/common/model/schema/apiCall/apiCall.schema.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { model, Schema } from "../../../mongodb" - -import { IApiCall } from "./apiCall.types" - -export const apiCallSchema = new Schema( - { - caller: { - type: String, - require: true, - description: "Le service faisant appel à l'API", - }, - api_path: { - type: String, - require: true, - description: "Le endpoint appelé", - }, - response: { - type: String, - require: true, - description: "Le résultat de l'appel", - }, - training_count: { - type: Number, - default: 0, - description: "Le nombre de formations retournées", - }, - job_count: { - type: Number, - default: 0, - description: "Le nombre d'opportunités d'emploi retournées", - }, - result_count: { - type: Number, - default: 0, - description: "Le nombre total d'items retournés", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date d'ajout en base de données", - }, - }, - { - versionKey: false, - } -) - -export default model("apicalls", apiCallSchema) diff --git a/server/src/common/model/schema/apiCall/apiCall.types.ts b/server/src/common/model/schema/apiCall/apiCall.types.ts deleted file mode 100644 index 8ec9d91e17..0000000000 --- a/server/src/common/model/schema/apiCall/apiCall.types.ts +++ /dev/null @@ -1,11 +0,0 @@ -interface IApiCall { - caller: string - api_path: string - response: string - training_count: number - job_count: number - result_count: number - created_at: Date -} - -export type { IApiCall } diff --git a/server/src/common/model/schema/application/anonymizedApplications.schema.ts b/server/src/common/model/schema/application/anonymizedApplications.schema.ts deleted file mode 100644 index fb79c326d5..0000000000 --- a/server/src/common/model/schema/application/anonymizedApplications.schema.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { allLbaItemType } from "shared/constants/lbaitem" -import { IAnonymizedApplication } from "shared/models/anonymizedApplications.model" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const anonymizedApplicationSchema = new Schema( - { - company_recruitment_intention: { - type: String, - default: null, - required: false, - description: "L'intention de la société vis à vis du candidat", - }, - company_feedback_date: { - type: Date, - default: null, - required: false, - description: "Date d'intention/avis donnée", - }, - company_siret: { - type: String, - default: null, - description: "Le siret de l'établissement", - index: true, - }, - company_naf: { - type: String, - default: null, - description: "Le label naf de la société", - }, - job_origin: { - type: String, - default: null, - enum: allLbaItemType, - description: "Le type de société / offre au sens source d'info La bonne alternance", - }, - job_id: { - type: String, - default: null, - description: "L'id externe de l'offre d'emploi", - index: true, - }, - caller: { - type: String, - default: null, - description: "L'identification de la source d'émission de la candidature (pour widget et api)", - }, - created_at: { - type: Date, - default: Date.now, - description: "La date création de la demande", - }, - }, - { - versionKey: false, - } -) - -anonymizedApplicationSchema.plugin(mongoosePagination) - -export default model>("anonymizedapplications", anonymizedApplicationSchema) diff --git a/server/src/common/model/schema/application/applications.schema.ts b/server/src/common/model/schema/application/applications.schema.ts deleted file mode 100644 index b4a184be4f..0000000000 --- a/server/src/common/model/schema/application/applications.schema.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { IApplication } from "shared" -import { allLbaItemType } from "shared/constants/lbaitem" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const applicationSchema = new Schema( - { - applicant_email: { - type: String, - default: null, - description: "Adresse email candidat", - }, - applicant_first_name: { - type: String, - default: null, - description: "Prénom du candidat", - }, - applicant_last_name: { - type: String, - default: null, - description: "Nom du candidat", - }, - applicant_phone: { - type: String, - default: null, - description: "Téléphone du candidat", - }, - applicant_attachment_name: { - type: String, - default: null, - description: "Nom du fichier du CV du candidat", - }, - applicant_message_to_company: { - type: String, - default: null, - required: false, - description: "Le message envoyé par le candidat", - }, - company_recruitment_intention: { - type: String, - default: null, - required: false, - description: "L'intention de la société vis à vis du candidat", - }, - company_feedback: { - type: String, - default: null, - required: false, - description: "L'avis donné par la société", - }, - company_feedback_date: { - type: Date, - default: null, - required: false, - description: "Date d'intention/avis donnée", - }, - company_siret: { - type: String, - default: null, - description: "Le siret de l'établissement", - index: true, - }, - company_email: { - type: String, - default: null, - description: "L'adresse email de destination de la candidature", - index: true, - }, - company_name: { - type: String, - default: null, - description: "Le nom de la société", - }, - company_naf: { - type: String, - default: null, - description: "Le label naf de la société", - }, - company_address: { - type: String, - default: null, - description: "L'adresse physique de la société", - }, - job_origin: { - type: String, - default: null, - enum: allLbaItemType, - description: "Le type de société / offre au sens source d'info La bonne alternance", - }, - job_title: { - type: String, - default: null, - description: "Le titre de l'offre à laquelle répond le candidat", - }, - job_id: { - type: String, - default: null, - description: "L'id externe de l'offre d'emploi", - index: true, - }, - to_applicant_message_id: { - type: String, - default: null, - description: "Identifiant chez le transporteur du mail envoyé au candidat", - index: true, - }, - to_company_message_id: { - type: String, - default: null, - description: "Identifiant chez le transporteur du mail envoyé à l'entreprise", - index: true, - }, - caller: { - type: String, - default: null, - description: "L'identification de la source d'émission de la candidature (pour widget et api)", - index: true, - }, - created_at: { - type: Date, - default: Date.now, - description: "La date création de la demande", - }, - last_update_at: { - type: Date, - default: Date.now, - description: "Date de dernières mise à jour", - }, - }, - { - versionKey: false, - } -) - -applicationSchema.plugin(mongoosePagination) - -// Indexes to support checkUserApplicationCount -applicationSchema.index({ applicant_email: 1, created_at: 1 }) -applicationSchema.index({ applicant_email: 1, company_siret: 1 }) -applicationSchema.index({ applicant_email: 1, job_id: 1 }) -applicationSchema.index({ caller: 1, company_siret: 1, created_at: 1 }) - -export default model>("applications", applicationSchema) diff --git a/server/src/common/model/schema/appointmentDetailed/appointmentDetailed.schema.ts b/server/src/common/model/schema/appointmentDetailed/appointmentDetailed.schema.ts deleted file mode 100644 index b4e34bfbe9..0000000000 --- a/server/src/common/model/schema/appointmentDetailed/appointmentDetailed.schema.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IAppointment } from "shared" - -import { model } from "../../../mongodb" -import { appointmentSchema } from "../appointments/appointment.schema" - -export default model("appointmentDetailed", appointmentSchema) diff --git a/server/src/common/model/schema/appointments/appointment.schema.ts b/server/src/common/model/schema/appointments/appointment.schema.ts deleted file mode 100644 index 4ecaa061b3..0000000000 --- a/server/src/common/model/schema/appointments/appointment.schema.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { IAppointment } from "shared" -import { AppointmentUserType } from "shared/constants/appointment" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const appointmentSchema = new Schema( - { - applicant_id: { - type: String, - require: true, - description: "Id candidat", - index: true, - }, - cfa_intention_to_applicant: { - type: String, - default: null, - description: "Type de réponse du CFA à la demande de RDV (personalised_answer/other_channel/no_answer)", - }, - cfa_message_to_applicant_date: { - type: Date, - default: null, - description: "Date d'envoi de la réponse du CFA à la demande de RDV", - }, - cfa_message_to_applicant: { - type: String, - default: null, - description: "Message de réponse du CFA à la demande de RDV", - }, - applicant_message_to_cfa: { - type: String, - default: null, - required: false, - description: "Les motivations du candidat", - }, - applicant_reasons: { - type: "array", - default: null, - required: false, - description: "Les raisons qui poussent le candidat à écrire", - }, - cfa_gestionnaire_siret: { - type: String, - default: null, - description: "SIRET gestionnaire", - }, - cfa_formateur_siret: { - type: String, - default: null, - description: "SIRET formateur", - }, - appointment_origin: { - type: String, - require: true, - description: "Le nom du site parent", - }, - cfa_read_appointment_details_date: { - type: Date, - default: null, - description: "Date à laquelle le CFA à consulté la page contenant les informations du rendez et du candidat", - }, - to_applicant_mails: { - type: "array", - description: "Liste des évènements MAIL récupéré par le serveur", - required: false, - default: [], - items: { - type: "object", - required: false, - properties: { - campaign: { - type: "string", - default: null, - description: "Identifiant de campagne", - }, - message_id: { - type: "string", - default: null, - description: "Identifiant Brevo", - }, - status: { - type: "string", - default: null, - description: "Code erreur Brevo", - }, - webhook_status_at: { - type: Date, - default: null, - description: "Date fournie par les webhooks Brevo lors de la réception d'un event", - }, - email_sent_at: { - type: Date, - default: null, - description: "Date de création de la collection", - }, - }, - }, - }, - to_cfa_mails: { - type: "array", - description: "Liste des évènements MAIL récupéré par le serveur", - required: false, - default: [], - items: { - type: "object", - required: false, - properties: { - campaign: { - type: "string", - default: null, - description: "Identifiant de campagne", - }, - message_id: { - type: "string", - default: null, - description: "Identifiant Brevo", - }, - status: { - type: "string", - default: null, - description: "Code erreur Brevo", - }, - webhook_status_at: { - type: Date, - default: null, - description: "Date fournie par les webhooks Brevo lors de la réception d'un event", - }, - email_sent_at: { - type: Date, - default: null, - description: "Date de création de la collection", - }, - }, - }, - }, - cle_ministere_educatif: { - type: String, - default: null, - description: "Identifiant unique d'une formation", - index: true, - }, - created_at: { - type: Date, - default: Date.now, - description: "La date création de la demande", - }, - cfa_recipient_email: { - type: String, - required: false, - default: null, - description: "Adresse email CFA", - }, - applicant_type: { - type: String, - enum: [...Object.values(AppointmentUserType), null], - default: null, - description: "Role du demandeur : parent ou etudiant", - }, - }, - { - versionKey: false, - } -) - -appointmentSchema.plugin(mongoosePagination) -appointmentSchema.index({ applicant_id: 1, cle_ministere_educatif: 1, created_at: 1 }) - -export default model>("appointment", appointmentSchema) diff --git a/server/src/common/model/schema/credentials/credential.schema.ts b/server/src/common/model/schema/credentials/credential.schema.ts deleted file mode 100644 index c9189b5676..0000000000 --- a/server/src/common/model/schema/credentials/credential.schema.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { randomUUID } from "crypto" - -import { ICredential } from "shared" - -import { model, Schema } from "../../../mongodb" - -export const credentialSchema = new Schema( - { - nom: { - type: String, - required: true, - }, - prenom: { - type: String, - required: true, - }, - organisation: { - type: String, - required: true, - }, - scope: { - type: String, - required: true, - }, - email: { - type: String, - required: true, - }, - api_key: { - type: String, - default: () => `mna-${randomUUID()}`, - index: true, - required: true, - }, - actif: { - type: Boolean, - default: true, - }, - }, - { timestamps: true, versionKey: false } -) - -export default model("credential", credentialSchema) diff --git a/server/src/common/model/schema/customEmailETFA/customEmailETFA.schema.ts b/server/src/common/model/schema/customEmailETFA/customEmailETFA.schema.ts deleted file mode 100644 index 17d05d9c42..0000000000 --- a/server/src/common/model/schema/customEmailETFA/customEmailETFA.schema.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ICustomEmailETFA } from "shared" - -import { model, Schema } from "../../../mongodb" - -export const customEmailETFASchema = new Schema( - { - email: { - type: String, - }, - cle_ministere_educatif: { - type: String, - index: true, - }, - }, - { - versionKey: false, - timestamps: true, - } -) - -export default model("customEmailETFA", customEmailETFASchema) diff --git a/server/src/common/model/schema/diplomesmetiers/diplomesmetiers.schema.ts b/server/src/common/model/schema/diplomesmetiers/diplomesmetiers.schema.ts deleted file mode 100644 index bbe972c9ff..0000000000 --- a/server/src/common/model/schema/diplomesmetiers/diplomesmetiers.schema.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { model, Schema } from "../../../mongodb" - -import { IDiplomesMetiers } from "./diplomesmetiers.types" - -export const diplomesMetiersSchema = new Schema( - { - intitule_long: { - type: String, - require: true, - description: "Le nom long d'un diplôme", - }, - codes_romes: { - type: [String], - default: [], - description: "Les codes Romes associés au diplôme", - }, - codes_rncps: { - type: [String], - default: [], - description: "Les codes RNCPs associés au diplôme", - }, - acronymes_intitule: { - type: String, - require: true, - description: "Les acronymes construit à partir de l'intitulé", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date d'ajout en base de données", - }, - last_update_at: { - type: Date, - default: Date.now, - description: "Date de dernières mise à jour", - }, - }, - { - versionKey: false, - } -) - -export default model("diplomesmetiers", diplomesMetiersSchema) diff --git a/server/src/common/model/schema/diplomesmetiers/diplomesmetiers.types.ts b/server/src/common/model/schema/diplomesmetiers/diplomesmetiers.types.ts deleted file mode 100644 index 35919ca8f4..0000000000 --- a/server/src/common/model/schema/diplomesmetiers/diplomesmetiers.types.ts +++ /dev/null @@ -1,10 +0,0 @@ -interface IDiplomesMetiers { - intitule_long: string - codes_romes: string[] - codes_rncps: string[] - acronymes_intitule: string - created_at: Date - last_update_at: Date -} - -export type { IDiplomesMetiers } diff --git a/server/src/common/model/schema/domainesmetiers/domainesmetiers.schema.ts b/server/src/common/model/schema/domainesmetiers/domainesmetiers.schema.ts deleted file mode 100644 index 826605af28..0000000000 --- a/server/src/common/model/schema/domainesmetiers/domainesmetiers.schema.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { Schema, model } from "../../../mongodb" - -import { IDomainesMetiers } from "./domainesmetiers.types" - -export const domainesMetiersSchema = new Schema( - { - sous_domaine: { - type: String, - require: true, - description: "Le sous-domaine d'un métier", - }, - sous_domaine_sans_accent_computed: { - type: String, - require: true, - description: "Le sous-domaine d'un métier sans caractère accentué", - }, - domaine: { - type: String, - default: null, - description: "Le grand domaine d'un métier", - }, - domaine_sans_accent_computed: { - type: String, - default: null, - description: "Le grand domaine d'un métier sans caractère accentué", - }, - codes_romes: { - type: [String], - default: [], - description: "Les codes Romes associés au métier", - }, - intitules_romes: { - type: [String], - default: [], - description: "Les libellés des codes ROMEs associés au métier", - }, - intitules_romes_sans_accent_computed: { - type: [String], - default: [], - description: "Les libellés des codes ROMEs associés au métier sans caractère accentué", - }, - codes_rncps: { - type: [String], - default: [], - description: "Les codes RNCPs associés au métier", - }, - intitules_rncps: { - type: [String], - default: [], - description: "Les libellés des codes RNCPs associés au métier", - }, - intitules_rncps_sans_accent_computed: { - type: [String], - default: [], - description: "Les libellés des codes RNCPs associés au métier sans caractère accentué", - }, - mots_clefs: { - type: String, - require: true, - description: "Les mots clefs associés au métier", - }, - mots_clefs_sans_accent_computed: { - type: String, - require: true, - description: "Les mots clefs associés au métier sans caractère accentué", - }, - mots_clefs_specifiques: { - type: String, - require: true, - description: "Les mots clefs associés à une ligne spécifique du métier", - }, - mots_clefs_specifiques_sans_accent_computed: { - type: String, - require: true, - description: "Les mots clefs associés à une ligne spécifique du métier sans caractère accentué", - }, - appellations_romes: { - type: String, - require: true, - description: "Mots clefs tirés des appellations associées à un code ROME", - }, - appellations_romes_sans_accent_computed: { - type: String, - require: true, - description: "Mots clefs tirés des appellations associées à un code ROME sans caractère accentué", - }, - couples_appellations_rome_metier: { - type: [Object], - default: [], - description: "Couple Appellation, code et libelle ROME", - }, - codes_fap: { - type: [String], - default: [], - description: "Liste des codes FAP", - }, - intitules_fap: { - type: [String], - default: [], - description: "Mots clefs issus des libellés FAP", - }, - intitules_fap_sans_accent_computed: { - type: [String], - default: [], - description: "Mots clefs issus des libellés FAP sans caractère accentué", - }, - sous_domaine_onisep: { - type: [String], - default: [], - description: "Les sous-domaines onisep", - }, - sous_domaine_onisep_sans_accent_computed: { - type: [String], - default: [], - description: "Les sous-domaines onisep sans caractère accentué", - }, - couples_romes_metiers: { - type: [Object], - default: [], - description: "Couples codes ROMEs / intitulés correspondants au métier", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date d'ajout en base de données", - }, - last_update_at: { - type: Date, - default: Date.now, - description: "Date de dernières mise à jour", - }, - }, - { - versionKey: false, - } -) - -export default model("domainesmetiers", domainesMetiersSchema) diff --git a/server/src/common/model/schema/domainesmetiers/domainesmetiers.types.ts b/server/src/common/model/schema/domainesmetiers/domainesmetiers.types.ts deleted file mode 100644 index 0b213b166a..0000000000 --- a/server/src/common/model/schema/domainesmetiers/domainesmetiers.types.ts +++ /dev/null @@ -1,36 +0,0 @@ -interface IDomainesMetiers { - sous_domaine: string - sous_domaine_sans_accent_computed: string - domaine: string | null - domaine_sans_accent_computed: string | null - codes_romes: string[] - intitules_romes: string[] - intitules_romes_sans_accent_computed: string[] - codes_rncps: string[] - intitules_rncps: string[] - intitules_rncps_sans_accent_computed: string[] - mots_clefs: string - mots_clefs_sans_accent_computed: string - mots_clefs_specifiques: string - mots_clefs_specifiques_sans_accent_computed: string - appellations_romes: string - appellations_romes_sans_accent_computed: string - couples_appellations_rome_metier: { - codeRome: string - intitule: string - appellation: string - }[] - codes_fap: string[] - intitules_fap: string[] - intitules_fap_sans_accent_computed: string[] - sous_domaine_onisep: string[] - sous_domaine_onisep_sans_accent_computed: string[] - couples_romes_metiers: { - codeRome: string - intitule: string - }[] - created_at: Date - last_update_at: Date -} - -export type { IDomainesMetiers } diff --git a/server/src/common/model/schema/eligibleTrainingsForAppointment/eligibleTrainingsForAppointment.schema.ts b/server/src/common/model/schema/eligibleTrainingsForAppointment/eligibleTrainingsForAppointment.schema.ts deleted file mode 100644 index 785b8c9c02..0000000000 --- a/server/src/common/model/schema/eligibleTrainingsForAppointment/eligibleTrainingsForAppointment.schema.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { IEligibleTrainingsForAppointment } from "shared" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const eligibleTrainingsForAppointmentSchema = new Schema( - { - training_id_catalogue: { - type: String, - require: true, - description: "Identifiant d'une formation Catalogue", - }, - training_intitule_long: { - type: String, - require: true, - description: "Intitulé long de la formation autorisée", - }, - etablissement_formateur_zip_code: { - type: String, - require: true, - description: "Code postal du lieu de formation", - }, - training_code_formation_diplome: { - type: String, - require: true, - description: "CFD de la formation autorisée", - }, - lieu_formation_email: { - type: String, - default: null, - description: "Adresse email pour la prise de RDV", - }, - is_lieu_formation_email_customized: { - type: Boolean, - default: null, - description: "Spécifie si la synchronisation avec le catalogue ne doit pas écraser l'email_rdv", - }, - referrers: { - type: [String], - default: [], - description: "Liste des sites autorisés", - index: true, - }, - rco_formation_id: { - type: String, - default: null, - index: true, - description: "Id RCO formation", - }, - is_catalogue_published: { - type: Boolean, - require: true, - description: "Si la formation est publiée sur le Catalogue", - }, - last_catalogue_sync_date: { - type: Date, - default: Date.now, - description: "Date de la dernière synchronisation avec le Catalogue", - }, - parcoursup_id: { - type: String, - index: true, - default: null, - description: "Identifiant Parcoursup", - }, - parcoursup_visible: { - type: Boolean, - index: true, - default: null, - description: "Statut SLA Parcoursup", - }, - affelnet_visible: { - type: Boolean, - index: true, - default: null, - description: "Statut SLA Affelnet", - }, - cle_ministere_educatif: { - type: String, - require: true, - description: "Identifiant unique d'une formation", - index: true, - }, - etablissement_formateur_raison_sociale: { - type: String, - require: true, - description: "Raison sociale de l'établissement", - }, - etablissement_formateur_street: { - type: String, - require: true, - description: "Adresse de l'établissement formateur", - }, - departement_etablissement_formateur: { - type: String, - require: true, - description: "Département de l'établissement formateur", - }, - etablissement_formateur_city: { - type: String, - require: true, - description: "Localité de l'établissement formateur", - }, - lieu_formation_street: { - type: String, - require: true, - description: "Adresse du lieux de formation", - }, - lieu_formation_city: { - type: String, - require: true, - description: "Localité de la formation", - }, - lieu_formation_zip_code: { - type: String, - require: true, - description: "Localité de la formation code postal", - }, - etablissement_formateur_siret: { - type: String, - require: true, - description: "Siret formateur", - }, - etablissement_gestionnaire_siret: { - type: String, - require: true, - description: "Siret gestionnaire", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date de création du document", - }, - historization_date: { - type: Date, - default: null, - description: "Date d'historisation", - }, - }, - { - versionKey: false, - } -) - -eligibleTrainingsForAppointmentSchema.plugin(mongoosePagination) - -export default model>("eligible_trainings_for_appointments", eligibleTrainingsForAppointmentSchema) diff --git a/server/src/common/model/schema/eligibleTrainingsForAppointmentsHistory/eligibleTrainingsForAppointmentHistory.schema.ts b/server/src/common/model/schema/eligibleTrainingsForAppointmentsHistory/eligibleTrainingsForAppointmentHistory.schema.ts deleted file mode 100644 index a7b8f48f00..0000000000 --- a/server/src/common/model/schema/eligibleTrainingsForAppointmentsHistory/eligibleTrainingsForAppointmentHistory.schema.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IEligibleTrainingsForAppointment } from "shared" - -import { model } from "../../../mongodb" -import { eligibleTrainingsForAppointmentSchema } from "../eligibleTrainingsForAppointment/eligibleTrainingsForAppointment.schema" - -export default model("eligible_trainings_for_appointments_history", eligibleTrainingsForAppointmentSchema) diff --git a/server/src/common/model/schema/emailBlacklist/emailBlacklist.schema.ts b/server/src/common/model/schema/emailBlacklist/emailBlacklist.schema.ts deleted file mode 100644 index 377b72ff00..0000000000 --- a/server/src/common/model/schema/emailBlacklist/emailBlacklist.schema.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { IEmailBlacklist } from "shared" - -import { model, Schema } from "../../../mongodb" - -export const emailBlacklistSchema = new Schema( - { - email: { - type: String, - require: true, - description: "L'adresse d'un établissement", - index: true, - unique: true, - }, - blacklisting_origin: { - type: String, - require: true, - description: "Source de l'information de blacklisting", - }, - created_at: { - type: Date, - default: Date.now, - description: "La date création de l'enregistrement", - }, - }, - { - versionKey: false, - } -) - -export default model("emailblacklist", emailBlacklistSchema) diff --git a/server/src/common/model/schema/etablissements/etablissement.schema.ts b/server/src/common/model/schema/etablissements/etablissement.schema.ts deleted file mode 100644 index 2ea2340c93..0000000000 --- a/server/src/common/model/schema/etablissements/etablissement.schema.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { IEtablissement } from "shared" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const etablissementSchema = new Schema( - { - formateur_siret: { - type: String, - default: null, - description: "Siret formateur", - index: true, - }, - gestionnaire_siret: { - type: String, - index: true, - default: null, - description: "Siret gestionnaire", - }, - raison_sociale: { - type: String, - default: null, - description: "Raison sociale", - }, - formateur_address: { - type: String, - default: null, - description: "Adresse formateur", - }, - formateur_zip_code: { - type: String, - default: null, - description: "Code postal formateur", - }, - formateur_city: { - type: String, - default: null, - description: "Ville formateur", - }, - gestionnaire_email: { - type: String, - default: null, - description: "Email du decisionnaire de l'établissement", - }, - premium_invitation_date: { - type: Date, - default: null, - description: "Date d'invitation au Premium (Parcoursup)", - }, - premium_activation_date: { - type: Date, - index: true, - default: null, - description: "Date d'acceptation de l'offre Premium (Parcoursup)", - }, - premium_refusal_date: { - type: Date, - default: null, - description: "Date de refus de l'offre Premium (Parcoursup)", - }, - premium_follow_up_date: { - type: Date, - default: null, - description: "Date de relance de l'offre Premium (Parcoursup)", - }, - premium_affelnet_invitation_date: { - type: Date, - default: null, - description: "Date d'invitation au Premium (Affelnet)", - }, - premium_affelnet_activation_date: { - type: Date, - index: true, - default: null, - description: "Date d'acceptation au Premium (Affelnet)", - }, - premium_affelnet_refusal_date: { - type: Date, - default: null, - description: "Date de refus au Premium (Affelnet)", - }, - premium_affelnet_follow_up_date: { - type: Date, - default: null, - description: "Date de relance au Premium (Affelnet)", - }, - optout_invitation_date: { - type: Date, - default: null, - description: "Date d'invitation de l'opt-out", - }, - optout_activation_scheduled_date: { - type: Date, - default: null, - description: "Date à laquelle l'activation sera effective", - }, - optout_activation_date: { - type: Date, - index: true, - default: null, - description: "Date d'activation de l'opt-out", - }, - optout_refusal_date: { - type: Date, - default: null, - description: "Date de refus de l'opt-out", - }, - last_catalogue_sync_date: { - type: Date, - default: null, - description: "Date de la dernière synchronisation avec le Catalogue", - }, - to_CFA_invite_optout_last_message_id: { - type: String, - default: null, - description: "Identifiant chez le transporteur du dernier email d'invitation envoyé", - index: true, - }, - created_at: { - type: Date, - default: Date.now, - description: "Date de création de la collection", - }, - }, - { - versionKey: false, - } -) - -etablissementSchema.plugin(mongoosePagination) - -export default model>("etablissement", etablissementSchema) diff --git a/server/src/common/model/schema/etablissements/etablissement.types.ts b/server/src/common/model/schema/etablissements/etablissement.types.ts deleted file mode 100644 index d12d9a53a6..0000000000 --- a/server/src/common/model/schema/etablissements/etablissement.types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { IEtablissement } from "shared" - -export type { IEtablissement } diff --git a/server/src/common/model/schema/ficheRomeV4/ficheRomeV4.ts b/server/src/common/model/schema/ficheRomeV4/ficheRomeV4.ts deleted file mode 100644 index cbbc3647f1..0000000000 --- a/server/src/common/model/schema/ficheRomeV4/ficheRomeV4.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { IFicheMetierRomeV4 } from "shared/models" - -import { Schema, model } from "../../../mongodb" - -export const ficheMetierRomeV4Schema = new Schema( - { - rome_code: { - type: String, - description: "Code Rome", - }, - fiche_metier: { - type: Object, - description: "Fiche metier Rome V4", - }, - }, - { - versionKey: false, - } -) - -ficheMetierRomeV4Schema.index({ rome_code: 1 }) -ficheMetierRomeV4Schema.index({ "fiche_metier.appellations.code": 1 }) - -export default model("ficheMetierRomeV4", ficheMetierRomeV4Schema) diff --git a/server/src/common/model/schema/formationCatalogue/etablissement.formateur.sub.ts b/server/src/common/model/schema/formationCatalogue/etablissement.formateur.sub.ts deleted file mode 100644 index 3517c2992d..0000000000 --- a/server/src/common/model/schema/formationCatalogue/etablissement.formateur.sub.ts +++ /dev/null @@ -1,112 +0,0 @@ -export const etablissementFormateurInfo = { - etablissement_formateur_id: { - type: String, - description: "Identifiant établissement formateur", - }, - etablissement_formateur_siret: { - type: String, - description: "Numéro siret formateur", - require: true, - }, - etablissement_formateur_enseigne: { - type: String, - description: "Enseigne établissement formateur", - }, - etablissement_formateur_uai: { - type: String, - description: "UAI de l'etablissement formateur", - }, - etablissement_formateur_type: { - type: String, - description: "Etablissement formateur est un CFA ou un OF", - }, - etablissement_formateur_conventionne: { - type: String, - description: "Etablissement formateur est conventionné ou pas", - }, - etablissement_formateur_declare_prefecture: { - type: String, - description: "Etablissement formateur est déclaré en prefecture", - }, - etablissement_formateur_datadock: { - type: String, - description: "Etablissement formateur est connu de datadock", - }, - etablissement_formateur_published: { - type: Boolean, - description: "Etablissement formateur est publié", - }, - etablissement_formateur_catalogue_published: { - type: Boolean, - description: "Etablissement formateur entre dans le catalogue", - }, - etablissement_formateur_adresse: { - type: String, - description: "Numéro et rue établissement formateur", - }, - etablissement_formateur_code_postal: { - type: String, - description: "Code postal établissement formateur", - }, - etablissement_formateur_code_commune_insee: { - type: String, - description: "Code commune insee établissement formateur", - }, - etablissement_formateur_localite: { - type: String, - description: "Localité établissement formateur", - }, - etablissement_formateur_complement_adresse: { - type: String, - description: "Complément d'adresse de l'établissement", - }, - etablissement_formateur_cedex: { - type: String, - description: "Cedex", - }, - etablissement_formateur_entreprise_raison_sociale: { - type: String, - description: "Raison sociale établissement formateur", - }, - geo_coordonnees_etablissement_formateur: { - type: String, - implicit_type: "geo_point", - description: "Latitude et longitude de l'établissement formateur", - }, - rncp_etablissement_formateur_habilite: { - type: Boolean, - description: "Etablissement formateur est habilité RNCP ou pas", - }, - etablissement_formateur_region: { - type: String, - description: "région formateur", - }, - etablissement_formateur_num_departement: { - type: String, - description: "Numéro de departement formateur", - }, - etablissement_formateur_nom_departement: { - type: String, - description: "Nom du departement formateur", - }, - etablissement_formateur_nom_academie: { - type: String, - description: "Nom de l'académie formateur", - }, - etablissement_formateur_num_academie: { - type: String, - description: "Numéro de l'académie formateur", - }, - etablissement_formateur_siren: { - type: String, - description: "Numéro siren formateur", - }, - etablissement_formateur_date_creation: { - type: Date, - description: "Date de création de l'établissement", - }, - etablissement_formateur_courriel: { - type: String, - description: "Email de l'établissement", - }, -} diff --git a/server/src/common/model/schema/formationCatalogue/etablissement.gestionnaire.sub.ts b/server/src/common/model/schema/formationCatalogue/etablissement.gestionnaire.sub.ts deleted file mode 100644 index 105921ce11..0000000000 --- a/server/src/common/model/schema/formationCatalogue/etablissement.gestionnaire.sub.ts +++ /dev/null @@ -1,111 +0,0 @@ -export const etablissementGestionnaireInfo = { - etablissement_gestionnaire_id: { - type: String, - description: "Identifiant établissement gestionnaire", - }, - etablissement_gestionnaire_siret: { - type: String, - description: "Numéro siret gestionnaire", - }, - etablissement_gestionnaire_enseigne: { - type: String, - description: "Enseigne établissement gestionnaire", - }, - etablissement_gestionnaire_uai: { - type: String, - description: "UAI de l'etablissement gestionnaire", - }, - etablissement_gestionnaire_type: { - type: String, - description: "Etablissement gestionnaire est un CFA ou un OF", - }, - etablissement_gestionnaire_conventionne: { - type: String, - description: "Etablissement gestionnaire est conventionné ou pas", - }, - etablissement_gestionnaire_declare_prefecture: { - type: String, - description: "Etablissement gestionnaire est déclaré en prefecture", - }, - etablissement_gestionnaire_datadock: { - type: String, - description: "Etablissement gestionnaire est connu de datadock", - }, - etablissement_gestionnaire_published: { - type: Boolean, - description: "Etablissement gestionnaire est publié", - }, - etablissement_gestionnaire_catalogue_published: { - type: Boolean, - description: "Etablissement gestionnaire entre dans le catalogue", - }, - etablissement_gestionnaire_adresse: { - type: String, - description: "Numéro et rue établissement gestionnaire", - }, - etablissement_gestionnaire_code_postal: { - type: String, - description: "Code postal établissement gestionnaire", - }, - etablissement_gestionnaire_code_commune_insee: { - type: String, - description: "Code commune insee établissement gestionnaire", - }, - etablissement_gestionnaire_localite: { - type: String, - description: "Localité établissement gestionnaire", - }, - etablissement_gestionnaire_complement_adresse: { - type: String, - description: "Complément d'adresse de l'établissement gestionnaire", - }, - etablissement_gestionnaire_cedex: { - type: String, - description: "Cedex", - }, - etablissement_gestionnaire_entreprise_raison_sociale: { - type: String, - description: "Raison sociale établissement gestionnaire", - }, - geo_coordonnees_etablissement_gestionnaire: { - type: String, - implicit_type: "geo_point", - description: "Latitude et longitude de l'établissement gestionnaire", - }, - rncp_etablissement_gestionnaire_habilite: { - type: Boolean, - description: "Etablissement gestionnaire est habilité RNCP ou pas", - }, - etablissement_gestionnaire_region: { - type: String, - description: "région gestionnaire", - }, - etablissement_gestionnaire_num_departement: { - type: String, - description: "Numéro de departement gestionnaire", - }, - etablissement_gestionnaire_nom_departement: { - type: String, - description: "Nom du departement gestionnaire", - }, - etablissement_gestionnaire_nom_academie: { - type: String, - description: "Nom de l'académie gestionnaire", - }, - etablissement_gestionnaire_num_academie: { - type: String, - description: "Numéro de l'académie gestionnaire", - }, - etablissement_gestionnaire_siren: { - type: String, - description: "Numéro siren gestionnaire", - }, - etablissement_gestionnaire_date_creation: { - type: Date, - description: "Date de création de l'établissement", - }, - etablissement_gestionnaire_courriel: { - type: String, - description: "Email de l'établissement", - }, -} diff --git a/server/src/common/model/schema/formationCatalogue/etablissement.reference.sub.ts b/server/src/common/model/schema/formationCatalogue/etablissement.reference.sub.ts deleted file mode 100644 index 52a5922e05..0000000000 --- a/server/src/common/model/schema/formationCatalogue/etablissement.reference.sub.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const etablissementReferenceInfo = { - etablissement_reference: { - type: String, - description: "Etablissement reference est soit formateur soit le gestionnaire", - }, - etablissement_reference_published: { - type: Boolean, - description: "Etablissement reference est publié", - }, - etablissement_reference_habilite_rncp: { - type: Boolean, - description: "Etablissement reference est habilité RNCP ou pas", - }, - etablissement_reference_certifie_qualite: { - type: Boolean, - description: "Etablissement reference est certifié Qualité", - }, - etablissement_reference_date_creation: { - type: Date, - description: "Date de création de l'établissement", - }, -} diff --git a/server/src/common/model/schema/formationCatalogue/formationCatalogue.schema.ts b/server/src/common/model/schema/formationCatalogue/formationCatalogue.schema.ts deleted file mode 100644 index fd09a5a948..0000000000 --- a/server/src/common/model/schema/formationCatalogue/formationCatalogue.schema.ts +++ /dev/null @@ -1,501 +0,0 @@ -import { IFormationCatalogue } from "shared" - -import { model, Schema } from "../../../mongodb" -import { geoPointSchema } from "../geopoint/geoPoint.schema" - -import { etablissementFormateurInfo } from "./etablissement.formateur.sub" -import { etablissementGestionnaireInfo } from "./etablissement.gestionnaire.sub" -import { etablissementReferenceInfo } from "./etablissement.reference.sub" - -const mnaFormationSchema = new Schema( - { - cle_ministere_educatif: { - index: true, - type: String, - description: "Clé unique de la formation (pour envoi aux ministères éducatifs)", - }, - cfd: { - index: true, - type: String, - description: "Code formation diplome (education nationale)", - }, - cfd_specialite: { - type: Object, - description: "Lettre spécialité du code cfd", - }, - cfd_outdated: { - type: Boolean, - description: "BCN : cfd périmé (fermeture avant le 31 aout de l'année courante)", - }, - cfd_date_fermeture: { - type: Date, - description: "Date de fermeture du cfd", - }, - cfd_entree: { - index: true, - type: String, - description: "Code formation diplome d'entrée (année 1 de l'apprentissage)", - }, - mef_10_code: { - type: String, - description: "Code MEF 10 caractères", - }, - mefs_10: { - type: [Object], - description: "Tableau de Code MEF 10 caractères et modalités (filtrés pour Affelnet si applicable)", - }, - nom_academie: { - type: String, - description: "Nom de l'académie", - }, - num_academie: { - type: String, - description: "Numéro de l'académie", - }, - code_postal: { - type: String, - description: "Code postal", - }, - code_commune_insee: { - type: String, - description: "Code commune INSEE", - }, - num_departement: { - type: String, - description: "Numéro de departement", - }, - nom_departement: { - type: String, - description: "Nom du departement", - }, - region: { - type: String, - description: "Numéro de departement", - }, - localite: { - type: String, - description: "Localité", - }, - uai_formation: { - index: true, - type: String, - description: "UAI du lieu de la formation", - }, - nom: { - type: String, - description: "Nom de la formation déclaratif", - }, - intitule_long: { - type: String, - description: "Intitulé long de la formation normalisé BCN", - }, - intitule_rco: { - type: String, - description: "Intitulé RCO de la formation", - }, - intitule_court: { - type: String, - description: "Intitulé court de la formation normalisé BCN", - }, - diplome: { - type: String, - description: "Diplôme ou titre visé", - }, - niveau: { - type: String, - description: "Niveau de la formation", - index: true, - }, - onisep_url: { - type: String, - description: "Url de redirection vers le site de l'ONISEP", - }, - - onisep_intitule: { - type: String, - description: "Intitulé éditorial l'ONISEP", - }, - - onisep_libelle_poursuite: { - type: String, - description: "Libellé poursuite étude l'ONISEP (séparateur ;)", - }, - onisep_lien_site_onisepfr: { - type: String, - description: "Lien vers site de l'ONISEP api", - }, - onisep_discipline: { - type: String, - description: "Disciplines ONISEP (séparateur ;)", - }, - onisep_domaine_sousdomaine: { - type: String, - description: "Domaine et sous domaine ONISEP (séparateur ;)", - }, - rncp_code: { - index: true, - type: String, - description: "Code RNCP", - }, - rncp_intitule: { - type: String, - description: "Intitulé du code RNCP", - }, - rncp_eligible_apprentissage: { - type: Boolean, - description: "Le titre RNCP est éligible en apprentissage", - }, - rncp_details: { - type: { - date_fin_validite_enregistrement: { - type: String, - description: "Date de validité de la fiche", - }, - active_inactive: { - type: String, - description: "fiche active ou non", - }, - etat_fiche_rncp: { - type: String, - description: "état fiche ex: Publiée", - }, - niveau_europe: { - type: String, - description: "Niveau europeen ex: niveauu5", - }, - code_type_certif: { - type: String, - description: "Code type de certification (ex: DE)", - }, - type_certif: { - type: String, - description: "Type de certification (ex: diplome d'etat)", - }, - ancienne_fiche: { - type: [String], - description: "Code rncp de l'ancienne fiche", - }, - nouvelle_fiche: { - type: [String], - description: "Code rncp de la nouvelle fiche", - }, - demande: { - type: Number, - description: "demande en cours de d'habilitation", - }, - certificateurs: { - type: [Object], - description: "Certificateurs", - }, - nsf_code: { - type: String, - description: "code NSF", - }, - nsf_libelle: { - type: String, - description: "libéllé NSF", - }, - romes: { - type: [Object], - description: "Romes", - }, - blocs_competences: { - type: [Object], - description: "Blocs de compétences", - }, - voix_acces: { - type: [Object], - description: "voix d'accès", - }, - partenaires: { - type: [Object], - description: "partenaires", - }, - }, - description: "Détails RNCP (bloc de compétences etc..)", - }, - rome_codes: { - type: [String], - description: "Codes ROME", - index: true, - }, - date_debut: { - type: [Date], - description: "Dates de début de session", - }, - date_fin: { - type: [Date], - description: "Dates de fin de session", - }, - modalites_entrees_sorties: { - type: [Boolean], - description: "Session en entrée / sortie permanente", - }, - capacite: { - type: String, - description: "Capacité d'accueil", - }, - duree: { - type: String, - description: "Durée de la formation en années", - }, - annee: { - type: String, - description: "Année de la formation (cursus)", - }, - email: { - type: String, - noIndex: true, - description: "Email du contact pour cette formation", - }, - parcoursup_reference: { - type: Boolean, - description: "La formation est présent sur parcourSup", - }, - parcoursup_a_charger: { - type: Boolean, - description: "La formation doit être ajouter à ParcourSup", - }, - parcoursup_statut: { - type: String, - enum: [ - "hors périmètre", - "publié", - "non publié", - "à publier (sous condition habilitation)", - "à publier (vérifier accès direct postbac)", - "à publier (soumis à validation Recteur)", - "à publier", - "en attente de publication", - ], - description: "Statut parcoursup", - }, - parcoursup_statut_history: { - type: [Object], - description: "Parcoursup : historique des statuts", - noIndex: true, - }, - parcoursup_error: { - type: String, - description: "Erreur lors de la création de la formation sur ParcourSup (via le WS)", - }, - parcoursup_id: { - index: true, - type: String, - description: "ids ParcourSup", - }, - parcoursup_visible: { - type: Boolean, - description: "Formation Parcoursup visible sur le SLA", - }, - affelnet_reference: { - type: Boolean, - description: "La formation est présent sur affelnet", - }, - affelnet_a_charger: { - type: Boolean, - description: "**[DEPRECATED]** La formation doit être ajouter à affelnet", - }, - affelnet_statut: { - type: String, - enum: ["hors périmètre", "publié", "non publié", "à publier (soumis à validation)", "à publier", "en attente de publication"], - description: "Statut affelnet", - }, - affelnet_statut_history: { - type: [Object], - description: "Affelnet : historique des statuts", - noIndex: true, - }, - affelnet_visible: { - type: Boolean, - description: "Formation Affelnet visible sur le SLA", - }, - source: { - type: String, - description: "Origine de la formation", - }, - commentaires: { - type: String, - description: "Commentaires", - }, - opcos: { - type: [String], - description: "Liste des opcos de la formation", - }, - info_opcos: { - type: Number, - description: "Code du statut de liaison avec un/des opcos", - }, - info_opcos_intitule: { - type: String, - description: "Intitule du statut de liaison avec un/des opcos", - }, - published: { - index: true, - type: Boolean, - description: "Est publiée, la formation est éligible pour le catalogue", - }, - rco_published: { - type: Boolean, - description: "Est publiée dans le flux rco", - }, - draft: { - type: Boolean, - description: "En cours de creation", - }, - created_at: { - type: Date, - description: "Date d'ajout en base de données", - }, - updates_history: { - type: [Object], - description: "Historique des mises à jours", - noIndex: true, - }, - last_update_at: { - type: Date, - description: "Date de dernières mise à jour", - }, - last_update_who: { - type: String, - description: "Qui a réalisé la derniere modification", - }, - // Flags - to_update: { - index: true, - type: Boolean, - description: "Formation à mette à jour lors du script d'enrichissement", - }, - update_error: { - type: String, - description: "Erreur lors de la mise à jour de la formation", - }, - lieu_formation_geo_coordonnees: { - type: String, - implicit_type: "geo_point", - description: "Latitude et longitude du lieu de formation", - }, - lieu_formation_geopoint: { - type: geoPointSchema, - default: null, - description: "La géolocation du lieu de formation sous forme de geoPoint", - }, - lieu_formation_adresse: { - type: String, - description: "Adresse du lieu de formation", - }, - lieu_formation_adresse_computed: { - type: String, - description: "Adresse du lieu de formation déduit de la géolocalisation le flux RCO", - }, - lieu_formation_siret: { - type: String, - description: "Siret du lieu de formation", - }, - id_rco_formation: { - index: true, - type: String, - description: "Id de formation RCO (id_formation + id_action + id_certifinfo)", - }, - id_formation: { - index: true, - type: String, - description: "Identifiant de la formation", - }, - id_action: { - index: true, - type: String, - description: "Identifant des actions concaténés", - }, - ids_action: { - index: true, - type: [String], - description: "Identifant des actions concaténés", - }, - id_certifinfo: { - index: true, - type: String, - description: "Identifant certifInfo (unicité de la certification)", - }, - tags: { - type: [String], - description: "Tableau de tags (2020, 2021, etc.)", - index: true, - }, - libelle_court: { - type: String, - description: "BCN : libelle court fusion table n_formation_diplome ou v_formation_diplome", - }, - niveau_formation_diplome: { - type: String, - description: "BCN : niveau formation diplome", - }, - affelnet_infos_offre: { - type: String, - description: "Affelnet : Informations offre de formation", - }, - affelnet_code_nature: { - type: String, - description: "Affelnet : code nature de l'établissement de formation", - }, - affelnet_secteur: { - type: String, - enum: ["PR", "PU", null], - description: "Affelnet : type d'établissement (PR: Privé / PU: Public)", - }, - affelnet_raison_depublication: { - type: String, - description: "Affelnet : raison de dépublication", - }, - bcn_mefs_10: { - type: [Object], - description: "BCN : Codes MEF 10 caractères", - }, - editedFields: { - type: Object, - description: "Champs édités par un utilisateur", - }, - parcoursup_raison_depublication: { - type: String, - description: "Parcoursup : raison de dépublication", - }, - distance_lieu_formation_etablissement_formateur: { - type: Number, - description: "distance entre le Lieu de formation et l'établissement formateur", - }, - niveau_entree_obligatoire: { - type: Number, - description: "Niveau d'entrée de l'apprenti minimum obligatoire pour cette formation", - }, - entierement_a_distance: { - type: Boolean, - description: "Renseigné si la formation peut être suivie entièrement à distance", - }, - catalogue_published: { - index: true, - type: Boolean, - description: "Formation éligible au catalogue générale", - }, - contenu: { - type: String, - description: "Le descriptif de la formation", - }, - objectif: { - type: String, - description: "Les objectifs de la formation", - }, - num_tel: { - type: String, - default: null, - description: "Numéro de téléphone de contact de la formation", - }, - ...etablissementGestionnaireInfo, - ...etablissementFormateurInfo, - ...etablissementReferenceInfo, - }, - { - versionKey: false, - } -) - -export default model("formationcatalogues", mnaFormationSchema) diff --git a/server/src/common/model/schema/formationCatalogue/mnaFormation.ts b/server/src/common/model/schema/formationCatalogue/mnaFormation.ts deleted file mode 100644 index d6b7b702cb..0000000000 --- a/server/src/common/model/schema/formationCatalogue/mnaFormation.ts +++ /dev/null @@ -1,463 +0,0 @@ -import { IFormationCatalogue } from "shared" - -import { model, Schema } from "../../../mongodb" - -import { etablissementFormateurInfo } from "./etablissement.formateur.sub" -import { etablissementGestionnaireInfo } from "./etablissement.gestionnaire.sub" -import { etablissementReferenceInfo } from "./etablissement.reference.sub" - -const mnaFormationSchema = new Schema( - { - cle_ministere_educatif: { - index: true, - type: String, - description: "Clé unique de la formation (pour envoi aux ministères éducatifs)", - }, - cfd: { - index: true, - type: String, - description: "Code formation diplome (education nationale)", - }, - cfd_specialite: { - type: Object, - description: "Lettre spécialité du code cfd", - }, - cfd_outdated: { - type: Boolean, - description: "BCN : cfd périmé (fermeture avant le 31 aout de l'année courante)", - }, - cfd_date_fermeture: { - type: Date, - description: "Date de fermeture du cfd", - }, - cfd_entree: { - index: true, - type: String, - description: "Code formation diplome d'entrée (année 1 de l'apprentissage)", - }, - mef_10_code: { - type: String, - description: "Code MEF 10 caractères", - }, - mefs_10: { - type: [Object], - description: "Tableau de Code MEF 10 caractères et modalités (filtrés pour Affelnet si applicable)", - }, - nom_academie: { - type: String, - description: "Nom de l'académie", - }, - num_academie: { - type: String, - description: "Numéro de l'académie", - }, - code_postal: { - type: String, - description: "Code postal", - }, - code_commune_insee: { - type: String, - description: "Code commune INSEE", - }, - num_departement: { - type: String, - description: "Numéro de departement", - }, - nom_departement: { - type: String, - description: "Nom du departement", - }, - region: { - type: String, - description: "Numéro de departement", - }, - localite: { - type: String, - description: "Localité", - }, - uai_formation: { - index: true, - type: String, - description: "UAI du lieu de la formation", - }, - nom: { - type: String, - description: "Nom de la formation déclaratif", - }, - intitule_long: { - type: String, - description: "Intitulé long de la formation normalisé BCN", - }, - intitule_court: { - type: String, - description: "Intitulé court de la formation normalisé BCN", - }, - intitule_rco: { - type: String, - description: "Intitulé RCO de la formation", - }, - diplome: { - type: String, - description: "Diplôme ou titre visé", - }, - niveau: { - type: String, - description: "Niveau de la formation", - }, - onisep_url: { - type: String, - description: "Url de redirection vers le site de l'ONISEP", - }, - - onisep_intitule: { - type: String, - description: "Intitulé éditorial l'ONISEP", - }, - - onisep_libelle_poursuite: { - type: String, - description: "Libellé poursuite étude l'ONISEP (séparateur ;)", - }, - onisep_lien_site_onisepfr: { - type: String, - description: "Lien vers site de l'ONISEP api", - }, - onisep_discipline: { - type: String, - description: "Disciplines ONISEP (séparateur ;)", - }, - onisep_domaine_sousdomaine: { - type: String, - description: "Domaine et sous domaine ONISEP (séparateur ;)", - }, - - rncp_code: { - index: true, - type: String, - description: "Code RNCP", - }, - rncp_intitule: { - type: String, - description: "Intitulé du code RNCP", - }, - rncp_eligible_apprentissage: { - type: Boolean, - description: "Le titre RNCP est éligible en apprentissage", - }, - rncp_details: { - type: { - date_fin_validite_enregistrement: { - type: String, - description: "Date de validité de la fiche", - }, - active_inactive: { - type: String, - description: "fiche active ou non", - }, - etat_fiche_rncp: { - type: String, - description: "état fiche ex: Publiée", - }, - niveau_europe: { - type: String, - description: "Niveau europeen ex: niveauu5", - }, - code_type_certif: { - type: String, - description: "Code type de certification (ex: DE)", - }, - type_certif: { - type: String, - description: "Type de certification (ex: diplome d'etat)", - }, - ancienne_fiche: { - type: [String], - description: "Code rncp de l'ancienne fiche", - }, - nouvelle_fiche: { - type: [String], - description: "Code rncp de la nouvelle fiche", - }, - demande: { - type: Number, - description: "demande en cours de d'habilitation", - }, - certificateurs: { - type: [Object], - description: "Certificateurs", - }, - nsf_code: { - type: String, - description: "code NSF", - }, - nsf_libelle: { - type: String, - description: "libéllé NSF", - }, - romes: { - type: [Object], - description: "Romes", - }, - blocs_competences: { - type: [Object], - description: "Blocs de compétences", - }, - voix_acces: { - type: [Object], - description: "voix d'accès", - }, - partenaires: { - type: [Object], - description: "partenaires", - }, - }, - description: "Détails RNCP (bloc de compétences etc..)", - }, - rome_codes: { - type: [String], - description: "Codes ROME", - }, - capacite: { - type: String, - description: "Capacité d'accueil", - }, - duree: { - type: String, - description: "Durée de la formation en années", - }, - annee: { - type: String, - description: "Année de la formation (cursus)", - }, - email: { - type: String, - noIndex: true, - description: "Email du contact pour cette formation", - }, - parcoursup_reference: { - type: Boolean, - description: "La formation est présent sur parcourSup", - }, - parcoursup_a_charger: { - type: Boolean, - description: "La formation doit être ajouter à ParcourSup", - }, - parcoursup_statut: { - type: String, - enum: [ - "hors périmètre", - "publié", - "non publié", - "à publier (sous condition habilitation)", - "à publier (vérifier accès direct postbac)", - "à publier (soumis à validation Recteur)", - "à publier", - "en attente de publication", - ], - description: "Statut parcoursup", - }, - parcoursup_statut_history: { - type: [Object], - description: "Parcoursup : historique des statuts", - noIndex: true, - }, - parcoursup_error: { - type: String, - description: "Erreur lors de la création de la formation sur ParcourSup (via le WS)", - }, - parcoursup_id: { - index: true, - type: String, - description: "ids ParcourSup", - }, - affelnet_reference: { - type: Boolean, - description: "La formation est présent sur affelnet", - }, - affelnet_a_charger: { - type: Boolean, - description: "**[DEPRECATED]** La formation doit être ajouter à affelnet", - }, - affelnet_statut: { - type: String, - enum: ["hors périmètre", "publié", "non publié", "à publier (soumis à validation)", "à publier", "en attente de publication"], - description: "Statut affelnet", - }, - affelnet_statut_history: { - type: [Object], - description: "Affelnet : historique des statuts", - noIndex: true, - }, - source: { - type: String, - description: "Origine de la formation", - }, - commentaires: { - type: String, - description: "Commentaires", - }, - opcos: { - type: [String], - description: "Liste des opcos de la formation", - }, - info_opcos: { - type: Number, - description: "Code du statut de liaison avec un/des opcos", - }, - info_opcos_intitule: { - type: String, - description: "Intitule du statut de liaison avec un/des opcos", - }, - published: { - index: true, - type: Boolean, - description: "Est publiée, la formation est éligible pour le catalogue", - }, - rco_published: { - type: Boolean, - description: "Est publiée dans le flux rco", - }, - draft: { - type: Boolean, - description: "En cours de creation", - }, - created_at: { - type: Date, - description: "Date d'ajout en base de données", - }, - updates_history: { - type: [Object], - description: "Historique des mises à jours", - noIndex: true, - }, - last_update_at: { - type: Date, - description: "Date de dernières mise à jour", - }, - last_update_who: { - type: String, - description: "Qui a réalisé la derniere modification", - }, - - // Flags - to_update: { - index: true, - type: Boolean, - description: "Formation à mette à jour lors du script d'enrichissement", - }, - - update_error: { - type: String, - description: "Erreur lors de la mise à jour de la formation", - }, - - lieu_formation_geo_coordonnees: { - type: String, - implicit_type: "geo_point", - description: "Latitude et longitude du lieu de formation", - }, - lieu_formation_adresse: { - type: String, - description: "Adresse du lieu de formation", - }, - lieu_formation_adresse_computed: { - type: String, - description: "Adresse du lieu de formation déduit de la géolocalisation le flux RCO", - }, - lieu_formation_siret: { - type: String, - description: "Siret du lieu de formation", - }, - id_rco_formation: { - index: true, - type: String, - description: "Id de formation RCO (id_formation + id_action + id_certifinfo)", - }, - id_formation: { - index: true, - type: String, - description: "Identifiant de la formation", - }, - id_action: { - index: true, - type: String, - description: "Identifant des actions concaténés", - }, - ids_action: { - index: true, - type: [String], - description: "Identifant des actions concaténés", - }, - id_certifinfo: { - index: true, - type: String, - description: "Identifant certifInfo (unicité de la certification)", - }, - tags: { - type: [String], - description: "Tableau de tags (2020, 2021, etc.)", - }, - libelle_court: { - type: String, - description: "BCN : libelle court fusion table n_formation_diplome ou v_formation_diplome", - }, - niveau_formation_diplome: { - type: String, - description: "BCN : niveau formation diplome", - }, - affelnet_infos_offre: { - type: String, - description: "Affelnet : Informations offre de formation", - }, - affelnet_code_nature: { - type: String, - description: "Affelnet : code nature de l'établissement de formation", - }, - affelnet_secteur: { - type: String, - enum: ["PR", "PU", null], - description: "Affelnet : type d'établissement (PR: Privé / PU: Public)", - }, - affelnet_raison_depublication: { - type: String, - description: "Affelnet : raison de dépublication", - }, - bcn_mefs_10: { - type: [Object], - description: "BCN : Codes MEF 10 caractères", - }, - editedFields: { - type: Object, - description: "Champs édités par un utilisateur", - }, - parcoursup_raison_depublication: { - type: String, - description: "Parcoursup : raison de dépublication", - }, - distance_lieu_formation_etablissement_formateur: { - type: Number, - description: "distance entre le Lieu de formation et l'établissement formateur", - }, - niveau_entree_obligatoire: { - type: Number, - description: "Niveau d'entrée de l'apprenti minimum obligatoire pour cette formation", - }, - entierement_a_distance: { - type: Boolean, - description: "Renseigné si la formation peut être suivie entièrement à distance", - }, - catalogue_published: { - index: true, - type: Boolean, - description: "Formation éligible au catalogue générale", - }, - ...etablissementGestionnaireInfo, - ...etablissementFormateurInfo, - ...etablissementReferenceInfo, - }, - { - versionKey: false, - } -) - -export default model("formationcatalogues", mnaFormationSchema) diff --git a/server/src/common/model/schema/geolocation/geolocation.schema.ts b/server/src/common/model/schema/geolocation/geolocation.schema.ts deleted file mode 100644 index 0def5f3407..0000000000 --- a/server/src/common/model/schema/geolocation/geolocation.schema.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { model, Schema } from "../../../mongodb" - -import { IGeolocation } from "./geolocation.types" - -export const geolocationSchema = new Schema( - { - address: { - type: String, - default: null, - description: "L'adresse d'un établissement", - index: true, - unique: true, - }, - city: { - type: String, - default: null, - description: "Ville", - }, - zip_code: { - type: String, - default: null, - description: "Code postal", - }, - geo_coordinates: { - type: String, - default: null, - description: "Les coordonnées latitude et longitude", - }, - }, - { - versionKey: false, - } -) - -export default model("geolocation", geolocationSchema) diff --git a/server/src/common/model/schema/geolocation/geolocation.types.ts b/server/src/common/model/schema/geolocation/geolocation.types.ts deleted file mode 100644 index a9d6521c4c..0000000000 --- a/server/src/common/model/schema/geolocation/geolocation.types.ts +++ /dev/null @@ -1,8 +0,0 @@ -interface IGeolocation { - address: string - city: string - zip_code: string - geo_coordinates: string -} - -export type { IGeolocation } diff --git a/server/src/common/model/schema/geopoint/geoPoint.schema.ts b/server/src/common/model/schema/geopoint/geoPoint.schema.ts deleted file mode 100644 index ca09672956..0000000000 --- a/server/src/common/model/schema/geopoint/geoPoint.schema.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Schema } from "../../../mongodb" - -export const geoPointSchema = new Schema<{ - type: string - coordinates: number[] -}>({ - _id: false, - type: { type: String, default: "Point" }, - coordinates: { - type: [Number], - default: [], - description: "Coordonnées [longitude,latitude] du point", - }, -}) diff --git a/server/src/common/model/schema/internalJobs/internalJobs.schema.ts b/server/src/common/model/schema/internalJobs/internalJobs.schema.ts deleted file mode 100644 index c18d0b1f3d..0000000000 --- a/server/src/common/model/schema/internalJobs/internalJobs.schema.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { model, Schema } from "../../../mongodb" - -import { IInternalJobs } from "./internalJobs.types" - -export const internalJobsSchema = new Schema( - { - name: { type: String, description: "Le nom de la tâche" }, - type: { - type: String, - enum: ["simple", "cron", "cron_task"], - description: "Type du job simple ou cron", - }, - status: { - type: String, - enum: ["pending", "will_start", "running", "finished", "blocked", "errored"], - description: "Statut courant du job", - }, - sync: { - type: Boolean, - description: "Si le job est synchrone", - }, - payload: { - type: Schema.Types.Mixed, - description: "La donnée liéé à la tâche", - }, - output: { - type: Schema.Types.Mixed, - description: "Les valeurs de retours du job", - }, - cron_string: { - type: String, - description: "standard cron string exemple: '*/2 * * * *'", - }, - scheduled_for: { - type: Date, - description: "Date de lancement programmée", - }, - started_at: { - type: Date, - description: "Date de lancement", - }, - ended_at: { - type: Date, - description: "Date de fin d'execution", - }, - updated_at: { - type: Date, - description: "Date de mise à jour en base de données", - }, - created_at: { - type: Date, - description: "Date d'ajout en base de données", - }, - }, - { - versionKey: false, - } -) -internalJobsSchema.index({ type: 1, scheduled_for: 1 }, { name: "type_scheduled_for" }) -internalJobsSchema.index({ type: 1, status: 1, scheduled_for: 1 }, { name: "type_status_scheduled_for" }) -internalJobsSchema.index({ ended_at: 1 }, { expireAfterSeconds: 3600 * 24 * 90 }) // 3 mois - -export default model("internalJob", internalJobsSchema) diff --git a/server/src/common/model/schema/jobs/jobs.schema.ts b/server/src/common/model/schema/jobs/jobs.schema.ts deleted file mode 100644 index 5e4cf0f38b..0000000000 --- a/server/src/common/model/schema/jobs/jobs.schema.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { IJob, JOB_STATUS } from "shared" -import { TRAINING_CONTRACT_TYPE } from "shared/constants/recruteur" - -import { model, Schema } from "../../../mongodb" - -export const jobsSchema = new Schema( - { - rome_label: { type: String, default: null, description: "Libellé du métier concerné" }, - rome_appellation_label: { type: String, default: null, description: "Libellé de l'appelation ROME" }, - job_level_label: { - type: String, - default: null, - description: "Niveau de formation visé en fin de stage", - }, - job_start_date: { - type: Date, - default: null, - description: "Date de début de l'alternance", - }, - job_description: { - type: String, - default: null, - description: "Description de l'offre d'alternance", - }, - job_employer_description: { - type: String, - default: null, - description: "Description de l'employer proposant l'offre d'alternance", - }, - rome_code: { - type: [String], - default: [], - description: "Liste des romes liés au métier", - }, - job_creation_date: { - type: Date, - default: null, - description: "Date de creation de l'offre", - }, - job_expiration_date: { - type: Date, - default: null, - description: "Date d'expiration de l'offre", - }, - job_update_date: { - type: Date, - default: Date.now, - description: "Date de dernière mise à jour de l'offre", - }, - job_last_prolongation_date: { - type: Date, - default: null, - description: "Date de dernière prolongation de l'offre", - }, - job_prolongation_count: { - type: Number, - default: 0, - description: "Nombre de fois où l'offre a été prolongée", - }, - relance_mail_sent: { - type: Boolean, - default: false, - description: "Statut de l'envoi du mail de relance avant expiration", - }, - job_status: { - type: String, - default: JOB_STATUS.ACTIVE, - enum: Object.values(JOB_STATUS), - description: "Statut de l'offre", - }, - job_status_comment: { - type: String, - description: "Raison de la suppression de l'offre", - }, - job_type: { - type: [String], - default: TRAINING_CONTRACT_TYPE.APPRENTISSAGE, - enum: Object.values(TRAINING_CONTRACT_TYPE), - description: "Type de contrat", - }, - is_multi_published: { - type: Boolean, - default: true, - description: "Definit si l'offre doit être diffusée sur d'autres jobboard que La bonne alternance", - }, - job_delegation_count: { - type: Number, - default: 0, - description: "Nombre de délégations", - }, - delegations: { - type: Array, - description: "Liste des délégations", - required: false, - items: { - type: Object, - required: false, - properties: { - siret_code: { - type: String, - require: true, - description: "SIRET de l'établissement", - }, - email: { - type: String, - require: true, - description: "Email gestionnaire de l'établissement", - }, - cfa_read_company_detail_at: { - type: Date, - default: null, - description: "Date de consultation de l'offre", - }, - }, - }, - }, - is_disabled_elligible: { - type: Boolean, - description: "Poste ouvert aux personnes en situation de handicap", - }, - job_count: { - type: Number, - description: "Nombre de poste(s) ouvert(s) pour cette offre", - }, - job_duration: { - type: Number, - description: "Durée du contrat en année", - }, - job_rythm: { - type: String, - description: "Répartition de la présence de l'alternant en formation/entreprise", - }, - custom_address: { - type: String, - default: null, - description: "Adresse personnalisée de l'entreprise", - }, - custom_geo_coordinates: { - type: String, - default: null, - description: "Latitude/Longitude de l'adresse personnalisée de l'entreprise", - }, - custom_job_title: { - type: String, - default: null, - description: "Titre personnalisée de l'offre", - }, - stats_detail_view: { - type: Number, - description: "Nombre de vues de la page de détail", - }, - stats_search_view: { - type: Number, - description: "Nombre de vues sur une page de recherche", - }, - managed_by: { - type: String, - description: "Id de l'utilisateur gérant l'offre", - }, - }, - { - versionKey: false, - } -) - -export default model("job", jobsSchema) diff --git a/server/src/common/model/schema/lbaCompany/lbaCompany.schema.ts b/server/src/common/model/schema/lbaCompany/lbaCompany.schema.ts deleted file mode 100644 index 2f963a8165..0000000000 --- a/server/src/common/model/schema/lbaCompany/lbaCompany.schema.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { ILbaCompany } from "shared" - -import { Schema, model } from "../../../mongodb" -import { geoPointSchema } from "../geopoint/geoPoint.schema" - -export const lbaCompanySchema = new Schema( - { - siret: { - type: String, - require: true, - description: "Le Siret de la société", - index: true, - }, - recruitment_potential: { - type: Number, - default: 0, - description: "Le score de recrutement de la société", - }, - raison_sociale: { - type: String, - default: null, - description: "Raison sociale de l'entreprise", - }, - enseigne: { - type: String, - require: true, - description: "Enseigne de l'entreprise", - }, - naf_code: { - type: String, - default: null, - description: "Code NAF de l'entreprise", - }, - naf_label: { - type: String, - default: null, - description: "Intitulé du code NAF", - }, - rome_codes: { - type: [String], - default: [], - description: "Liste des codes ROMEs au sein de l'entreprise", - index: true, - }, - street_number: { - type: String, - default: null, - description: "Numéro dans la rue", - }, - street_name: { - type: String, - default: null, - description: "Nom de la rue", - }, - insee_city_code: { - type: String, - default: null, - description: "Code commune INSEE", - }, - zip_code: { - type: String, - default: null, - description: "Code postal", - }, - city: { - type: String, - default: null, - description: "Ville", - }, - geo_coordinates: { - type: String, - implicit_type: "geo_point", - description: "Latitude et longitude de l'établissement", - }, - geopoint: { - type: geoPointSchema, - default: null, - description: "La géolocation du lieu sous forme de geoPoint", - }, - email: { - type: String, - default: null, - description: "Adresse email de contact", - }, - phone: { - type: String, - default: null, - description: "Numéro de téléphone de contact", - }, - company_size: { type: String, default: null, description: "Tranche effectif de l'entreprise" }, - website: { - type: String, - default: null, - description: "URL du site Internet", - }, - opco: { - type: String, - default: null, - description: "L'OPCO de la société", - index: true, - }, - opco_short_name: { - type: String, - default: null, - index: true, - description: "Nom court de l'opco", - }, - opco_url: { - type: String, - default: null, - description: "L'URL spécifique liée à l'OPCO de la société", - index: true, - }, - created_at: { - type: Date, - default: Date.now, - description: "La date création de la demande", - }, - last_update_at: { - type: Date, - default: Date.now, - description: "Date de dernières mise à jour", - }, - }, - { - versionKey: false, - } -) - -export default model("bonnesboites", lbaCompanySchema) diff --git a/server/src/common/model/schema/lbaCompanylegacy/lbaCompanyLegacy.schema.ts b/server/src/common/model/schema/lbaCompanylegacy/lbaCompanyLegacy.schema.ts deleted file mode 100644 index 777e21641f..0000000000 --- a/server/src/common/model/schema/lbaCompanylegacy/lbaCompanyLegacy.schema.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ILbaCompany } from "shared" - -import { Schema, model } from "../../../mongodb" -import { lbaCompanySchema } from "../lbaCompany/lbaCompany.schema" - -export const lbaCompanyLegacySchema = new Schema>( - { - siret: { - type: String, - require: true, - description: "Le Siret de la société", - index: true, - }, - email: { - type: String, - default: null, - description: "Adresse email de contact", - }, - }, - { - versionKey: false, - } -) -export default model>("bonnesboiteslegacy", lbaCompanySchema) diff --git a/server/src/common/model/schema/multiCompte/buildMongooseModel.ts b/server/src/common/model/schema/multiCompte/buildMongooseModel.ts deleted file mode 100644 index bf28f9d21a..0000000000 --- a/server/src/common/model/schema/multiCompte/buildMongooseModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -import mongoose, { Schema } from "mongoose" - -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -const { model } = mongoose - -export const buildMongooseModel = (schema: Schema, tableName: string) => { - schema.plugin(mongoosePagination) - - return model>(tableName, schema) -} diff --git a/server/src/common/model/schema/multiCompte/cfa.schema.ts b/server/src/common/model/schema/multiCompte/cfa.schema.ts deleted file mode 100644 index d5efa6b273..0000000000 --- a/server/src/common/model/schema/multiCompte/cfa.schema.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ICFA } from "shared/models/cfa.model.js" - -import { Schema } from "../../../mongodb.js" - -import { buildMongooseModel } from "./buildMongooseModel.js" - -const cfaSchema = new Schema( - { - origin: { - type: String, - description: "Origine de la creation (ex: Campagne mail, lien web, etc...) pour suivi", - }, - siret: { - type: String, - description: "Siret de l'établissement", - index: true, - }, - raison_sociale: { - type: String, - description: "Raison social de l'établissement", - }, - enseigne: { - type: String, - default: null, - description: "Enseigne de l'établissement", - }, - address_detail: { - type: Object, - description: "Detail de l'adresse de l'établissement", - }, - address: { - type: String, - description: "Adresse de l'établissement", - }, - geo_coordinates: { - type: String, - default: null, - description: "Latitude/Longitude de l'adresse de l'entreprise", - }, - }, - { - timestamps: true, - versionKey: false, - } -) - -export const Cfa = buildMongooseModel(cfaSchema, "cfa") diff --git a/server/src/common/model/schema/multiCompte/entreprise.schema.ts b/server/src/common/model/schema/multiCompte/entreprise.schema.ts deleted file mode 100644 index b3722d1716..0000000000 --- a/server/src/common/model/schema/multiCompte/entreprise.schema.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur.js" -import { EntrepriseStatus, IEntreprise, IEntrepriseStatusEvent } from "shared/models/entreprise.model.js" - -import { Schema } from "../../../mongodb.js" - -import { buildMongooseModel } from "./buildMongooseModel.js" - -const statusEventSchema = new Schema( - { - validation_type: { - type: String, - enum: Object.values(VALIDATION_UTILISATEUR), - description: "Indique si l'action est ordonnée par un utilisateur ou le serveur", - }, - status: { - type: String, - enum: Object.values(EntrepriseStatus), - description: "Statut", - index: true, - }, - reason: { - type: String, - description: "Raison du changement de statut", - }, - granted_by: { - type: String, - default: null, - description: "Utilisateur à l'origine du changement", - }, - date: { - type: Date, - default: () => new Date(), - description: "Date de l'évènement", - }, - }, - { _id: false } -) - -const entrepriseSchema = new Schema( - { - status: { - type: [statusEventSchema], - description: "Evénements liés au cycle de vie", - }, - origin: { - type: String, - description: "Origine de la creation de l'utilisateur (ex: Campagne mail, lien web, etc...) pour suivi", - }, - siret: { - type: String, - description: "Siret de l'établissement", - index: true, - }, - raison_sociale: { - type: String, - description: "Raison social de l'établissement", - }, - enseigne: { - type: String, - default: null, - description: "Enseigne de l'établissement", - }, - idcc: { - type: String, - description: "Identifiant convention collective de l'entreprise", - }, - address: { - type: String, - description: "Adresse de l'établissement", - }, - address_detail: { - type: Object, - description: "Detail de l'adresse de l'établissement", - }, - geo_coordinates: { - type: String, - default: null, - description: "Latitude/Longitude de l'adresse de l'entreprise", - }, - opco: { - type: String, - default: null, - description: "Information sur l'opco de l'entreprise", - }, - }, - { - timestamps: true, - versionKey: false, - } -) - -export const Entreprise = buildMongooseModel(entrepriseSchema, "entreprise") diff --git a/server/src/common/model/schema/multiCompte/roleManagement.schema.ts b/server/src/common/model/schema/multiCompte/roleManagement.schema.ts deleted file mode 100644 index 489d7c7905..0000000000 --- a/server/src/common/model/schema/multiCompte/roleManagement.schema.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur.js" -import { AccessEntityType, AccessStatus, IRoleManagement, IRoleManagementEvent } from "shared/models/roleManagement.model.js" - -import { ObjectId, Schema } from "../../../mongodb.js" - -import { buildMongooseModel } from "./buildMongooseModel.js" - -const roleManagementEventSchema = new Schema( - { - validation_type: { - type: String, - enum: Object.values(VALIDATION_UTILISATEUR), - description: "Indique si l'action est ordonnée par un utilisateur ou le serveur", - }, - status: { - type: String, - enum: Object.values(AccessStatus), - description: "Statut de l'accès", - index: true, - }, - reason: { - type: String, - description: "Raison du changement de statut", - }, - granted_by: { - type: String, - default: null, - description: "Utilisateur à l'origine du changement", - }, - date: { - type: Date, - default: () => new Date(), - description: "Date de l'évènement", - }, - }, - { _id: false } -) - -const roleManagementSchema = new Schema( - { - origin: { - type: String, - description: "Origine de la creation", - }, - status: { - type: [roleManagementEventSchema], - description: "Evénements liés au cycle de vie de l'accès", - }, - authorized_id: { - type: String, - description: "ID de l'entité sur laquelle l'accès est exercé", - index: true, - }, - authorized_type: { - type: String, - enum: Object.values(AccessEntityType), - description: "Type de l'entité sur laquelle l'accès est exercé", - index: true, - }, - user_id: { - type: ObjectId, - description: "ID de l'utilisateur ayant accès", - index: true, - }, - }, - { - timestamps: true, - versionKey: false, - } -) - -export const RoleManagement = buildMongooseModel(roleManagementSchema, "roleManagement") diff --git a/server/src/common/model/schema/multiCompte/userWithAccount.schema.ts b/server/src/common/model/schema/multiCompte/userWithAccount.schema.ts deleted file mode 100644 index b6d8f14f72..0000000000 --- a/server/src/common/model/schema/multiCompte/userWithAccount.schema.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur.js" -import { IUserWithAccount, IUserStatusEvent, UserEventType } from "shared/models/userWithAccount.model.js" - -import { Schema } from "../../../mongodb.js" - -import { buildMongooseModel } from "./buildMongooseModel.js" - -const userStatusEventSchema = new Schema( - { - validation_type: { - type: String, - enum: Object.values(VALIDATION_UTILISATEUR), - description: "Indique si l'action est ordonnée par un utilisateur ou le serveur", - }, - status: { - type: String, - enum: Object.values(UserEventType), - description: "Statut de l'utilisateur", - index: true, - }, - reason: { - type: String, - description: "Raison du changement de statut", - }, - granted_by: { - type: String, - default: null, - description: "Utilisateur à l'origine du changement", - }, - date: { - type: Date, - default: () => new Date(), - description: "Date de l'évènement", - }, - }, - { _id: false } -) - -const UserWithAccountSchema = new Schema( - { - origin: { - type: String, - description: "Origine de la creation de l'utilisateur (ex: Campagne mail, lien web, etc...) pour suivi", - }, - status: { - type: [userStatusEventSchema], - description: "Evénements liés au cycle de vie de l'utilisateur", - }, - first_name: { - type: String, - default: null, - description: "Le prénom", - }, - last_name: { - type: String, - default: null, - description: "Le nom", - }, - email: { - type: String, - default: null, - description: "L'email", - index: true, - unique: true, - }, - phone: { - type: String, - default: null, - description: "Le numéro de téléphone", - }, - last_action_date: { - type: Date, - default: null, - description: "Date de dernière connexion", - index: true, - }, - }, - { - timestamps: true, - versionKey: false, - } -) - -export const UserWithAccount = buildMongooseModel(UserWithAccountSchema, "userswithaccount") diff --git a/server/src/common/model/schema/opco/opco.schema.ts b/server/src/common/model/schema/opco/opco.schema.ts deleted file mode 100644 index b804c85eda..0000000000 --- a/server/src/common/model/schema/opco/opco.schema.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { model, Schema } from "../../../mongodb" - -import { IOpco } from "./opco.types" - -export const opcoSchema = new Schema( - { - siren: { - type: String, - require: true, - description: "Le SIREN d'un ", - index: true, - unique: true, - }, - opco: { - type: String, - require: true, - index: true, - description: "Nom de l'opco", - }, - opco_short_name: { - type: String, - default: null, - index: true, - description: "Nom court de de l'opco servant de clef dans notre table de constantes", - }, - idcc: { - type: String, - default: null, - index: true, - description: "Identifiant convention collective", - }, - url: { - type: String, - default: null, - index: true, - description: "Site internet de l'opco", - }, - }, - { - versionKey: false, - } -) - -export default model("opco", opcoSchema) diff --git a/server/src/common/model/schema/opco/opco.types.ts b/server/src/common/model/schema/opco/opco.types.ts deleted file mode 100644 index 727476d6b8..0000000000 --- a/server/src/common/model/schema/opco/opco.types.ts +++ /dev/null @@ -1,9 +0,0 @@ -interface IOpco { - siren: string - opco: string - opco_short_name?: string | null | undefined - idcc: string | null | undefined - url?: string | null | undefined -} - -export type { IOpco } diff --git a/server/src/common/model/schema/optout/optout.schema.ts b/server/src/common/model/schema/optout/optout.schema.ts deleted file mode 100644 index ff7e374ddb..0000000000 --- a/server/src/common/model/schema/optout/optout.schema.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { IOptout } from "shared" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const optoutSchema = new Schema( - { - etat: { - type: String, - description: "Etat administratif de l'organisme de formation", - }, - uai: { - type: [String], - description: "UAI potentiel de l'organisme de formation", - }, - rue: { - type: String, - description: "Rue de l'organisme de formation", - }, - code_postal: { - type: String, - description: "Code postal de l'organisme de formation", - }, - commune: { - type: String, - description: "Commune de l'organisme de formation", - }, - siret: { - type: String, - description: "Numéro SIRET de l'organisme de formation", - }, - contacts: { - type: [Object], - description: "liste des contacts", - }, - qualiopi: { - type: Boolean, - description: "Certification QUALIOPI", - }, - raison_sociale: { - type: String, - default: null, - description: "Raison social de l'entreprise", - }, - adresse: { - type: String, - default: null, - description: "Adresse de l'entreprise", - }, - geo_coordonnees: { - type: String, - default: null, - description: "Latitude/Longitude (inversion lié à LBA) de l'adresse de l'entreprise", - }, - mail: { - type: [ - { - email: { - type: String, - }, - messageId: { - type: String, - }, - date: { - type: Date, - default: () => new Date(), - }, - }, - ], - description: "Interaction avec les contacts", - }, - }, - { - timestamps: true, - versionKey: false, - } -) - -optoutSchema.plugin(mongoosePagination) - -export default model>("optout", optoutSchema) diff --git a/server/src/common/model/schema/recruiter/anonymizedRecruiter.schema.ts b/server/src/common/model/schema/recruiter/anonymizedRecruiter.schema.ts deleted file mode 100644 index c1e4df9fbb..0000000000 --- a/server/src/common/model/schema/recruiter/anonymizedRecruiter.schema.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IAnonymizedRecruiter } from "shared" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -import { nonPersonalInfosRecruiterSchema } from "./recruiter.schema" - -const anonymizedRecruiterSchema = new Schema( - { - ...nonPersonalInfosRecruiterSchema.obj, - }, - { - timestamps: true, - versionKey: false, - } -) - -anonymizedRecruiterSchema.index({ "jobs._id": 1 }) -anonymizedRecruiterSchema.plugin(mongoosePagination) - -export default model>("anonymizedrecruiter", anonymizedRecruiterSchema) diff --git a/server/src/common/model/schema/recruiter/recruiter.schema.ts b/server/src/common/model/schema/recruiter/recruiter.schema.ts deleted file mode 100644 index 21498cbf53..0000000000 --- a/server/src/common/model/schema/recruiter/recruiter.schema.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { randomUUID } from "crypto" - -import { IRecruiter } from "shared" - -import { RECRUITER_STATUS } from "../../../../services/constant.service" -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" -import { geoPointSchema } from "../geopoint/geoPoint.schema" -import { jobsSchema } from "../jobs/jobs.schema" - -const personalInfosRecruiterSchema = new Schema({ - last_name: { - type: String, - default: null, - description: "Nom du contact", - }, - first_name: { - type: String, - default: null, - description: "Prénom du contact", - }, - phone: { - type: String, - default: null, - description: "Téléphone du contact", - }, - email: { - type: String, - description: "Email du contact", - require: true, - }, - managed_by: { - type: String, - default: null, - description: "Id de l'utilisateur gestionnaire", - }, -}) - -export const nonPersonalInfosRecruiterSchema = new Schema({ - establishment_id: { - type: String, - default: () => randomUUID(), - description: "Identifiant de formulaire unique", - index: true, - }, - establishment_raison_sociale: { - type: String, - default: null, - description: "Raison social de l'entreprise", - }, - establishment_enseigne: { - type: String, - default: null, - description: "Enseigne de l'entreprise", - }, - establishment_siret: { - type: String, - require: true, - description: "Numéro SIRET de l'entreprise", - index: true, - }, - address_detail: { - type: Object, - description: "Détail de l'adresse de l'entreprise", - }, - address: { - type: String, - default: null, - description: "Adresse de l'entreprise", - }, - geo_coordinates: { - type: String, - default: null, - description: "Latitude/Longitude (inversion lié à LBA) de l'adresse de l'entreprise", - }, - geopoint: { - type: geoPointSchema, - default: null, - description: "La géolocation de l'adresse de l'entreprise sous forme de geoPoint", - }, - is_delegated: { - type: Boolean, - default: false, - description: "le formulaire est-il géré par un mandataire ?", - }, - cfa_delegated_siret: { - type: String, - description: "Siret de l'organisme de formation gestionnaire des offres de l'entreprise", - index: true, - }, - - jobs: [{ type: jobsSchema, default: {}, description: "Liste des offres d'apprentissage" }], - origin: { - type: String, - default: null, - description: "Origine/organisme lié au formulaire", - }, - opco: { - type: String, - description: "Information sur l'opco de l'entreprise", - }, - idcc: { - type: String, - description: "Identifiant convention collective de l'entreprise", - }, - status: { - type: String, - enum: Object.values(RECRUITER_STATUS), - default: RECRUITER_STATUS.ACTIF, - description: "Statut du formulaire", - }, - naf_code: { - type: String, - description: "code NAF de l'entreprise", - }, - naf_label: { - type: String, - description: "Libelle du code NAF de l'entreprise", - }, - establishment_size: { - type: String, - description: "Tranche d'effectif salariale de l'entreprise", - }, - establishment_creation_date: { - type: Date, - description: "Date de creation de l'entreprise", - }, -}) - -export const recruiterSchema = new Schema( - { - ...personalInfosRecruiterSchema.obj, - ...nonPersonalInfosRecruiterSchema.obj, - }, - { - timestamps: true, - versionKey: false, - } -) - -recruiterSchema.index({ "jobs._id": 1 }) -recruiterSchema.plugin(mongoosePagination) - -export default model>("recruiter", recruiterSchema) diff --git a/server/src/common/model/schema/recruteurLbaUpdateEvent/recruteurLbaUpdateEvent.schema.ts b/server/src/common/model/schema/recruteurLbaUpdateEvent/recruteurLbaUpdateEvent.schema.ts deleted file mode 100644 index 8cc0b99616..0000000000 --- a/server/src/common/model/schema/recruteurLbaUpdateEvent/recruteurLbaUpdateEvent.schema.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { IRecruteurLbaUpdateEvent } from "shared" - -import { Schema, model } from "../../../mongodb" - -export const recruteurLbaUpdateEventSchema = new Schema( - { - siret: { - type: String, - require: true, - description: "Le Siret de la société", - }, - event: { - type: String, - require: true, - description: "Le type de modification effectué", - }, - value: { - type: String, - default: "", - description: "La nouvelle valeur", - }, - created_at: { - type: Date, - default: Date.now, - description: "La date création de la demande", - }, - }, - { - versionKey: false, - } -) - -export default model("recruteurlbaupdateevents", recruteurLbaUpdateEventSchema) diff --git a/server/src/common/model/schema/referentielOnisep/referentielOnisep.schema.ts b/server/src/common/model/schema/referentielOnisep/referentielOnisep.schema.ts deleted file mode 100644 index 7f90a6fa6a..0000000000 --- a/server/src/common/model/schema/referentielOnisep/referentielOnisep.schema.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { IReferentielOnisep } from "shared/models" - -import { model, Schema } from "../../../mongodb" - -export const referentielOnisepSchema = new Schema( - { - id_action_ideo2: { - type: String, - required: true, - index: true, - description: "ID action IDEO2", - }, - cle_ministere_educatif: { - type: String, - required: true, - description: "Clé ministère educatif", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date de création", - }, - }, - { - versionKey: false, - } -) - -export default model("referentielOnisep", referentielOnisepSchema) diff --git a/server/src/common/model/schema/referentielOpco/referentielOpco.schema.ts b/server/src/common/model/schema/referentielOpco/referentielOpco.schema.ts deleted file mode 100644 index fa103b611c..0000000000 --- a/server/src/common/model/schema/referentielOpco/referentielOpco.schema.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { OPCOS } from "shared/constants/recruteur" -import { IReferentielOpco } from "shared/models" - -import { model, Schema } from "../../../mongodb" - -export const referentielOpcoSchema = new Schema( - { - opco_label: { - type: String, - required: true, - enum: Object.values(OPCOS), - description: "Dénomination de l'opco", - }, - siret_code: { - type: String, - description: "Siret de l'établissement", - index: true, - }, - emails: { - type: [String], - description: "Liste des emails disponibles pour l'établissement", - index: true, - }, - }, - { - versionKey: false, - } -) - -export const ReferentielOpco = model("referentielOpco", referentielOpcoSchema) - -export default ReferentielOpco diff --git a/server/src/common/model/schema/referentielRome/referentielRome.ts b/server/src/common/model/schema/referentielRome/referentielRome.ts deleted file mode 100644 index 935f45ce4f..0000000000 --- a/server/src/common/model/schema/referentielRome/referentielRome.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { IReferentielRome } from "shared/index" - -import { model, Schema } from "../../../mongodb.js" - -const codeRomeSchema = new Schema( - { code_rome: { type: String, index: true }, intitule: { type: String }, code_ogr: { type: String } }, - { - _id: false, - versionKey: false, - } -) - -export const referentielRomeSchema = new Schema( - { - numero: { - type: String, - description: "Numéro d'identification de la fiche emploi", - }, - rome: codeRomeSchema, - appellations: { - type: Array, - items: { - libelle: String, - libelle_court: String, - code_ogr: String, - }, - description: "Liste des appellations lié au code rome", - }, - definition: String, - acces_metier: String, - competences: { - savoir_faire: Array, - savoir_etre_professionnel: Array, - savoirs: Array, - }, - contextes_travail: { - type: Array, - }, - mobilites: { - type: Array, - }, - }, - { versionKey: false } -) - -export default model("referentielRomes", referentielRomeSchema) diff --git a/server/src/common/model/schema/session/session.schema.ts b/server/src/common/model/schema/session/session.schema.ts deleted file mode 100644 index c142d7de94..0000000000 --- a/server/src/common/model/schema/session/session.schema.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ISession } from "shared" - -import config from "@/config" - -import { model, Schema } from "../../../mongodb" - -export const sessionSchema = new Schema( - { - token: { - type: String, - description: "Token de la session", - }, - updated_at: { - type: Date, - default: Date.now, - description: "Date de mise à jour en base de données", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date d'ajout en base de données", - }, - expires_at: { - type: Date, - default: Date.now, - description: "Date d'expiration", - }, - }, - { - versionKey: false, - } -) - -sessionSchema.index({ token: 1 }) -sessionSchema.index({ expires_at: 1 }, { expireAfterSeconds: config.auth.session.cookie.maxAge / 100 }) - -export default model("session", sessionSchema) diff --git a/server/src/common/model/schema/siretDiffusibleStatusSchema/siretDiffusibleStatusSchema.schema.ts b/server/src/common/model/schema/siretDiffusibleStatusSchema/siretDiffusibleStatusSchema.schema.ts deleted file mode 100644 index e51fdc5891..0000000000 --- a/server/src/common/model/schema/siretDiffusibleStatusSchema/siretDiffusibleStatusSchema.schema.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ISiretDiffusibleStatus } from "shared/models" - -import { model, Schema } from "../../../mongodb" - -export const siretDiffusibleStatusSchema = new Schema( - { - siret: { - type: String, - require: true, - description: "Le siret cherché", - index: true, - unique: true, - }, - status_diffusion: { - type: String, - default: "diffusible", - description: "Le statut de diffusion : diffusible | partiellement_diffusible | non_diffusible", - }, - created_at: { - type: Date, - default: Date.now, - description: "Date d'ajout en base de données", - }, - last_update_at: { - type: Date, - default: Date.now, - description: "Date de dernières mise à jour", - }, - }, - { - versionKey: false, - } -) - -export default model("siretdiffusiblestatus", siretDiffusibleStatusSchema) diff --git a/server/src/common/model/schema/unsubscribedLbaCompany/unsubscribedLbaCompany.schema.ts b/server/src/common/model/schema/unsubscribedLbaCompany/unsubscribedLbaCompany.schema.ts deleted file mode 100644 index 3031a4b8b3..0000000000 --- a/server/src/common/model/schema/unsubscribedLbaCompany/unsubscribedLbaCompany.schema.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { IUnsubscribedLbaCompany } from "shared" - -import { model, Schema } from "../../../mongodb" -import { lbaCompanySchema } from "../lbaCompany/lbaCompany.schema" - -const { siret, raison_sociale, enseigne, naf_code, naf_label, rome_codes, insee_city_code, zip_code, city, company_size, created_at, last_update_at } = lbaCompanySchema.obj -const unsubscribedLbaCompanySchema = new Schema( - { - siret, - raison_sociale, - enseigne, - naf_code, - naf_label, - rome_codes, - insee_city_code, - zip_code, - city, - company_size, - created_at, - last_update_at, - unsubscribe_date: { - type: Date, - default: Date.now, - description: "Date de désinscription", - }, - unsubscribe_reason: { - type: String, - default: null, - description: "Raison de la désinscription", - }, - }, - { - versionKey: false, - } -) - -export const UnsubscribedLbaCompany = model("unsubscribedbonnesboites", unsubscribedLbaCompanySchema) - -export default UnsubscribedLbaCompany diff --git a/server/src/common/model/schema/unsubscribedOF/unsubscribeOF.schema.ts b/server/src/common/model/schema/unsubscribedOF/unsubscribeOF.schema.ts deleted file mode 100644 index c8487c054d..0000000000 --- a/server/src/common/model/schema/unsubscribedOF/unsubscribeOF.schema.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { IUnsubscribedOF } from "shared/models" - -import { model, Schema } from "../../../mongodb" - -const unsubscribedOFSchema = new Schema( - { - catalogue_id: { - type: String, - description: "Id de l'organisme dans le catalogue", - index: true, - }, - establishment_siret: { - type: String, - description: "Le Siret de l'organisme de formation", - index: true, - }, - unsubscribe_date: { - type: Date, - description: "Date de désinscription", - }, - }, - { - versionKey: false, - } -) - -export const UnsubscribeOF = model("unsubscribedOF", unsubscribedOFSchema) - -export default UnsubscribeOF diff --git a/server/src/common/model/schema/user/user.schema.ts b/server/src/common/model/schema/user/user.schema.ts deleted file mode 100644 index be5068df1e..0000000000 --- a/server/src/common/model/schema/user/user.schema.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { IUser } from "shared" - -import { model, Schema } from "../../../mongodb" -import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate" - -export const userSchema = new Schema( - { - firstname: { - type: String, - default: null, - description: "Le prénom du candidat", - }, - lastname: { - type: String, - default: null, - description: "Le nom du candidat", - }, - phone: { - type: String, - default: null, - description: "Le téléphone du candidat", - }, - email: { - type: String, - default: null, - description: "L'email du candidat", - index: true, - }, - type: { - type: String, - enum: ["parent", "etudiant"], - description: "Type d'utilisateur (parent, etudiant)", - }, - role: { - type: String, - default: null, - description: "candidat | administrator", - }, - last_action_date: { - type: Date, - default: Date.now(), - description: "Date de dernière candidature", - }, - }, - { - versionKey: false, - } -) - -userSchema.plugin(mongoosePagination) - -export default model>("user", userSchema) diff --git a/server/src/common/model/swaggerSchema/entreprise.ts b/server/src/common/model/swaggerSchema/entreprise.ts deleted file mode 100644 index 90360d8970..0000000000 --- a/server/src/common/model/swaggerSchema/entreprise.ts +++ /dev/null @@ -1,107 +0,0 @@ -import offre from "./offre" - -export default { - entreprise: { - type: "object", - properties: { - id_form: { - type: "string", - description: "Identifiant de formulaire unique, déduit par l'application", - }, - raison_sociale: { - type: "string", - description: "Raison social de l'entreprise, déduit par l'application", - }, - siret: { - type: "string", - required: true, - description: "Numéro SIRET de l'entreprise", - }, - adresse: { - type: "string", - description: "Adresse de l'entreprise, déduit par l'application", - }, - geo_coordonnees: { - type: "string", - description: "Longitude/Latitude de l'adresse de l'entreprise, déduit par l'application", - }, - nom: { - type: "string", - required: true, - description: "Nom du contact", - }, - prenom: { - type: "string", - required: true, - description: "Prénom du contact", - }, - telephone: { - type: "string", - required: true, - description: "Téléphone du contact", - }, - email: { - type: "string", - required: true, - description: "Email du contact", - }, - gestionnaire: { - type: "string", - description: "SIRET du CFA/OF gestionnaire de l'entreprise, déduit par l'application", - }, - mandataire: { - type: "boolean", - description: "L'entreprise est géré ou non par un CFA, déduit par l'application", - }, - mailing: { - type: "array", - description: "Liste des évènements MAIL récupéré par le serveur", - items: { - type: "object", - required: false, - properties: { - campagne: { - type: "string", - default: "string", - description: "Identifiant de campagne", - }, - messageId: { - type: "string", - default: "string", - description: "Identifiant Brevo", - }, - code: { - type: "string", - default: "string", - description: "Code erreur Brevo", - }, - message: { - type: "string", - default: "string", - description: "Message erreur Brevo", - }, - }, - }, - }, - events: { - type: "array", - description: "Liste des évènements Brevo gérés par le serveur", - }, - origine: { - type: "string", - description: "Origine/organisme lié au formulaire, déduit par l'application", - }, - offres: { ...offre, description: "Liste de(s) offre(s) rattachée(s)" }, - opco: { - type: "string", - description: "OPCO de rattachement de l'entreprise, déduit par l'application", - }, - statut: { - type: "string", - enum: ["Actif", "Archivé", "En attente de validation"], - default: "Actif", - description: "Statut de l'entreprise", - }, - }, - }, -} diff --git a/server/src/common/model/swaggerSchema/index.ts b/server/src/common/model/swaggerSchema/index.ts deleted file mode 100644 index f751fb4f8f..0000000000 --- a/server/src/common/model/swaggerSchema/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import requireAll from "require-all" - -import __dirname from "../../dirname" - -// eslint-disable-next-line import/no-mutable-exports -let models = {} - -function filterFile(filename) { - if (filename.endsWith("") && filename !== "index") { - return filename - } - - return false -} - -const modelsList = requireAll({ - dirname: __dirname(import.meta.url), - filter: (filename) => filterFile(filename), -}) - -Object.keys(modelsList).forEach((filename) => { - const model = modelsList[filename] - models = { ...models, ...model } -}) - -export default models diff --git a/server/src/common/model/swaggerSchema/offre.ts b/server/src/common/model/swaggerSchema/offre.ts deleted file mode 100644 index 4f97e86090..0000000000 --- a/server/src/common/model/swaggerSchema/offre.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { TRAINING_CONTRACT_TYPE, TRAINING_RYTHM } from "shared/constants/recruteur" -import { JOB_STATUS } from "shared/models" - -export default { - offre: { - type: "array", - default: [], - items: { - type: "object", - properties: { - libelle: { - type: "string", - description: "Libellé du métier concerné selon le référentiel La bonne alternance", - required: true, - }, - niveau: { - type: "string", - description: "Niveau de formation requis", - }, - date_debut_apprentissage: { - type: "string", - description: "Date de début de l'alternance", - required: true, - }, - description: { - type: "string", - description: "Description de l'offre d'alternance", - }, - romes: { - type: "array", - items: { - type: "string", - }, - description: "Liste des romes liés au métier", - required: true, - }, - rome_detail: { - type: "object", - description: "Détail du code ROME selon la nomenclature Pole emploi", - }, - date_creation: { - type: "string", - default: "system", - description: "Date de creation de l'offre", - }, - date_expiration: { - type: "string", - default: "system", - description: "Date d'expiration de l'offre", - }, - relance_mail_sent: { - type: "boolean", - default: "system", - description: "Statut de l'envoi du mail de relance avant expiration", - }, - statut: { - type: "string", - default: JOB_STATUS.ACTIVE, - enum: [Object.values(JOB_STATUS)], - description: "Statut de l'offre", - }, - type: { - type: "array", - items: { - type: "string", - }, - default: TRAINING_CONTRACT_TYPE.APPRENTISSAGE, - enum: Object.values(TRAINING_CONTRACT_TYPE), - description: "Type de contrat", - }, - multi_diffuser: { - type: "boolean", - default: null, - description: "Definit si l'offre est diffusée sur d'autres jobboard que La bonne alternance", - }, - delegate: { - type: "boolean", - description: "Definit si l'entreprise souhaite déléguer l'offre à un CFA", - }, - elligible_handicap: { - type: "boolean", - description: "Poste ouvert aux personnes en situation de handicap", - }, - quantite: { - type: "number", - description: "Nombre de poste(s) ouvert(s) pour cette offre", - }, - duree_contrat: { - type: "number", - description: "Durée du contrat en année", - }, - rythme_alternance: { - type: "string", - enum: [...Object.values(TRAINING_RYTHM), null], - description: "Répartition de la présence de l'alternant en formation/entreprise", - }, - }, - }, - }, -} diff --git a/server/src/common/model/swaggerSchema/utilisateur.ts b/server/src/common/model/swaggerSchema/utilisateur.ts deleted file mode 100644 index 220dec64d9..0000000000 --- a/server/src/common/model/swaggerSchema/utilisateur.ts +++ /dev/null @@ -1,62 +0,0 @@ -export default { - utilisateur: { - type: "object", - properties: { - nom: { - type: "string", - description: "Nom de l'utilisateur", - }, - prenom: { - type: "string", - description: "Prénom de l'utilisateur", - }, - organization: { - type: "string", - description: "Organisme de l'utilisateur", - }, - raison_sociale: { - type: "string", - description: "Raison social de l'établissement, déduit du SIRET", - }, - siret: { - type: "string", - description: "Siret de l'établissement", - }, - adresse: { - type: "string", - description: "Adresse de l'établissement, déduit du SIRET", - }, - geo_coordonnees: { - type: "string", - description: "Latitude/Longitude de l'adresse de l'entreprise, déduit du SIRET", - }, - telephone: { - type: "string", - description: "Téléphone de l'établissement", - }, - email: { - type: "string", - description: "L'email de l'utilisateur", - unique: true, - }, - scope: { - type: "string", - description: "Scope accessible par l'utilisateur, déduit par l'application", - }, - email_valide: { - type: "boolean", - default: false, - description: "Indicateur de confirmation de l'adresse mail par l'utilisateur", - }, - type: { - type: "string", - default: "CFA", - description: "Type d'utilisateur, déduit par l'application", - }, - last_connection: { - type: "date", - description: "Date de dernière connexion, déduit par l'application", - }, - }, - }, -} diff --git a/server/src/common/mongodb.ts b/server/src/common/mongodb.ts deleted file mode 100644 index 522d1edd77..0000000000 --- a/server/src/common/mongodb.ts +++ /dev/null @@ -1,44 +0,0 @@ -import mongodb from "mongodb" -import type { ObjectId as ObjectIdType } from "mongodb" -import mongoose from "mongoose" - -import config from "../config" - -import { logger } from "./logger" - -const { ObjectId } = mongodb -export { ObjectId } -export type { ObjectIdType } -export const mongooseInstance = mongoose -export const { model, Schema } = mongoose -// @ts-expect-error -export let db: ReturnType // eslint-disable-line import/no-mutable-exports - -export const connectToMongo = async (mongoUri = config.mongodb.uri) => { - logger.info(`MongoDB: Connection to ${mongoUri}`) - - try { - // Set up default mongoose connection - await mongooseInstance.connect(mongoUri, { - useNewUrlParser: true, - useUnifiedTopology: true, - useFindAndModify: false, - keepAlive: true, - autoIndex: false, - poolSize: 1_000, - }) - mongooseInstance.Promise = global.Promise // Get the default connection - db = mongooseInstance.connection - - logger.info("MongoDB: Connected") - return { db } - } catch (error: any) { - logger.error("MongoDB: connection error:", error.message) - throw new Error(`MongoDB: connection error`) - } -} - -export const closeMongoConnection = async () => { - logger.info("MongoDB: closing connection") - await mongooseInstance.disconnect() -} diff --git a/server/src/common/utils/mongodbUtils.ts b/server/src/common/utils/mongodbUtils.ts new file mode 100644 index 0000000000..6a74b03679 --- /dev/null +++ b/server/src/common/utils/mongodbUtils.ts @@ -0,0 +1,222 @@ +import { captureException } from "@sentry/node" +import { isEqual } from "lodash-es" +import { Collection, CollectionInfo, MongoClient, MongoServerError } from "mongodb" // to uncomment when migrated to V7 +import { IModelDescriptor } from "shared/models/common" +import { CollectionName, IDocument, modelDescriptors } from "shared/models/models" +import { zodToMongoSchema } from "zod-mongodb-schema" + +import config from "../../config" +import { logger } from "../logger" + +import { sleep } from "./asyncUtils" + +let mongodbClient: MongoClient | null = null +let mongodbClientState: string | 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, { + heartbeatFrequencyMS: 10_000, + retryWrites: true, + retryReads: true, + minPoolSize: config.env === "local" ? 0 : 5, + }) + + client.on("connectionPoolReady", () => { + logger.info("MongoDB reconnected") + mongodbClient = client + }) + + client.on("connectionPoolClosed", () => { + logger.warn("MongoDB closed") + mongodbClient = null + }) + + await client.connect() + // @ts-expect-error + mongodbClientState = client.topology.s.state + mongodbClient = client + logger.info("Connected to MongoDB") + + return client +} + +export const getMongodbClient = () => mongodbClient +export const getMongodbClientState = () => mongodbClientState + +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: string) => { + 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 + } + const indexes = await getDbCollection(descriptor.collectionName) + .listIndexes() + .toArray() + .catch((err) => { + // NamespaceNotFound + if (err.code === 26) { + return [] + } + throw err + }) + const indexesToRemove = new Set(indexes.filter((i) => i.name !== "_id_")) + + logger.info(`Create indexes for collection ${descriptor.collectionName}`) + await Promise.all( + descriptor.indexes.map(async ([index, options]): Promise => { + try { + const existingIndex = + // Use Object.entries because order matters + indexes.find((i) => isEqual(Object.entries(i.key), Object.entries(index)) || options.name === i.name) ?? null + + if (existingIndex) { + indexesToRemove.delete(existingIndex) + } + + await getDbCollection(descriptor.collectionName) + .createIndex(index, options) + .catch(async (err) => { + // IndexOptionsConflict & IndexKeySpecsConflict + if (err.code === 85 || err.code === 86) { + await getDbCollection(descriptor.collectionName).dropIndex(existingIndex.name) + await getDbCollection(descriptor.collectionName).createIndex(index, options) + } else { + throw err + } + }) + } catch (err) { + captureException(err) + logger.error(`Error creating indexes for ${descriptor.collectionName}: ${err}`) + } + }) + ) + + if (indexesToRemove.size > 0) { + logger.warn(`Dropping extra indexes for collection ${descriptor.collectionName}`, indexesToRemove) + await Promise.all(Array.from(indexesToRemove).map((index) => getDbCollection(descriptor.collectionName).dropIndex(index.name))) + } + } +} + +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/common/utils/sendTrackingEvent.ts b/server/src/common/utils/sendTrackingEvent.ts index fda6cabae1..8175f9f81c 100644 --- a/server/src/common/utils/sendTrackingEvent.ts +++ b/server/src/common/utils/sendTrackingEvent.ts @@ -1,10 +1,10 @@ -import { ZApiCallNew } from "shared/models" - -import { ApiCalls } from "../model/index" +import { ObjectId } from "mongodb" +import { IApiCall } from "shared/models" +import { getDbCollection } from "./mongodbUtils" import { sentryCaptureException } from "./sentryUtils" -const trackApiCall = async ({ +export const trackApiCall = async ({ caller, api_path, training_count = 0, @@ -20,7 +20,9 @@ const trackApiCall = async ({ result_count?: number }) => { try { - const apiCallParams = { + const apiCallParams: IApiCall = { + _id: new ObjectId(), + created_at: new Date(), caller, api_path, training_count, @@ -29,11 +31,8 @@ const trackApiCall = async ({ response, } - const apiCall = new ApiCalls(ZApiCallNew.parse(apiCallParams)) - await apiCall.save() + await getDbCollection("apicalls").insertOne(apiCallParams) } catch (err) { sentryCaptureException(err) } } - -export { trackApiCall } diff --git a/server/src/db/migrations/20231018202702-user-recruiter-first-last-name.ts b/server/src/db/migrations/20231018202702-user-recruiter-first-last-name.ts index ccb65275b8..65c93c7a66 100644 --- a/server/src/db/migrations/20231018202702-user-recruiter-first-last-name.ts +++ b/server/src/db/migrations/20231018202702-user-recruiter-first-last-name.ts @@ -46,7 +46,6 @@ export const up = async (db: Db) => { }, ], { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/20231109134624-remove_is_anonymized_from_applications.ts b/server/src/db/migrations/20231109134624-remove_is_anonymized_from_applications.ts index d42dac386a..a81b4afd8a 100755 --- a/server/src/db/migrations/20231109134624-remove_is_anonymized_from_applications.ts +++ b/server/src/db/migrations/20231109134624-remove_is_anonymized_from_applications.ts @@ -9,7 +9,6 @@ export const up = async (db: Db) => { $unset: { is_anonymized: "" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/20231120000000-cleaning_applications.ts b/server/src/db/migrations/20231120000000-cleaning_applications.ts index 34060fafeb..80ec404e3b 100755 --- a/server/src/db/migrations/20231120000000-cleaning_applications.ts +++ b/server/src/db/migrations/20231120000000-cleaning_applications.ts @@ -7,7 +7,6 @@ export const up = async (db: Db) => { { company_naf: null }, { $set: { company_naf: "" } }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) @@ -16,7 +15,6 @@ export const up = async (db: Db) => { { job_title: null }, { $set: { job_title: "" } }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/20231127120528-remove-password.ts b/server/src/db/migrations/20231127120528-remove-password.ts index 2ead3bf525..824a18cb4f 100644 --- a/server/src/db/migrations/20231127120528-remove-password.ts +++ b/server/src/db/migrations/20231127120528-remove-password.ts @@ -9,7 +9,6 @@ export const up = async (db: Db) => { $unset: { password: "" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/20231129093200-remove-username.ts b/server/src/db/migrations/20231129093200-remove-username.ts index 3eb319e670..08bcbf9b54 100644 --- a/server/src/db/migrations/20231129093200-remove-username.ts +++ b/server/src/db/migrations/20231129093200-remove-username.ts @@ -10,7 +10,6 @@ export const up = async (db: Db) => { $unset: { username: "" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/20231129170900-clean-referentielopcos.ts b/server/src/db/migrations/20231129170900-clean-referentielopcos.ts index cecabb98fd..ce93c24751 100644 --- a/server/src/db/migrations/20231129170900-clean-referentielopcos.ts +++ b/server/src/db/migrations/20231129170900-clean-referentielopcos.ts @@ -1,14 +1,14 @@ import { ZReferentielOpco } from "shared/models" import { logger } from "@/common/logger" -import { ReferentielOpco } from "@/common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" export const up = async () => { - const referentielOpcos = await ReferentielOpco.find({}).lean() + const referentielOpcos = await getDbCollection("referentielopcos").find({}).toArray() const toBeDeletedOpcos = referentielOpcos.filter((refOpco) => { return !ZReferentielOpco.safeParse(refOpco).success }) - await ReferentielOpco.deleteMany({ _id: { $in: toBeDeletedOpcos.map((opco) => opco._id) } }) + await getDbCollection("referentielopcos").deleteMany({ _id: { $in: toBeDeletedOpcos.map((opco) => opco._id) } }) logger.info("20231129170900-clean-referentielopcos") } diff --git a/server/src/db/migrations/20231211000000-trim-unsubscribed-lbacompanies.ts b/server/src/db/migrations/20231211000000-trim-unsubscribed-lbacompanies.ts index 5ef37831e2..d44a0c590a 100644 --- a/server/src/db/migrations/20231211000000-trim-unsubscribed-lbacompanies.ts +++ b/server/src/db/migrations/20231211000000-trim-unsubscribed-lbacompanies.ts @@ -25,7 +25,6 @@ export const up = async (db: Db) => { }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/20231227130954-remove-field-from-appointments.ts b/server/src/db/migrations/20231227130954-remove-field-from-appointments.ts index d4a343d536..5277ed88f7 100644 --- a/server/src/db/migrations/20231227130954-remove-field-from-appointments.ts +++ b/server/src/db/migrations/20231227130954-remove-field-from-appointments.ts @@ -3,27 +3,30 @@ import { Db } from "mongodb" const removeField = (db) => db.collection("appointments").updateMany({}, { $unset: { is_anonymized: "" } }) const anonymizeAppointments = (db) => - db.collection("appointments").aggregate([ - { - $match: { is_anonymized: true }, - }, - { - $project: { - applicant_id: 1, - cfa_intention_to_applicant: 1, - cfa_message_to_applicant_date: 1, - cfa_gestionnaire_siret: 1, - cfa_formateur_siret: 1, - cfa_read_appointment_details_date: 1, - appointment_origin: 1, - cle_ministere_educatif: 1, - created_at: 1, + db + .collection("appointments") + .aggregate([ + { + $match: { is_anonymized: true }, }, - }, - { - $merge: "anonymizedappointments", - }, - ]) + { + $project: { + applicant_id: 1, + cfa_intention_to_applicant: 1, + cfa_message_to_applicant_date: 1, + cfa_gestionnaire_siret: 1, + cfa_formateur_siret: 1, + cfa_read_appointment_details_date: 1, + appointment_origin: 1, + cle_ministere_educatif: 1, + created_at: 1, + }, + }, + { + $merge: "anonymizedappointments", + }, + ]) + .toArray() export const up = async (db: Db) => { await anonymizeAppointments(db) diff --git a/server/src/db/migrations/20240109100722-export-custom-email-from-etfa.ts b/server/src/db/migrations/20240109100722-export-custom-email-from-etfa.ts index 6dd67de921..4c11734a3a 100644 --- a/server/src/db/migrations/20240109100722-export-custom-email-from-etfa.ts +++ b/server/src/db/migrations/20240109100722-export-custom-email-from-etfa.ts @@ -1,16 +1,30 @@ -import { CustomEmailETFA, EligibleTrainingsForAppointment } from "../../common/model" +import { ObjectId } from "mongodb" +import { ICustomEmailETFA } from "shared/models" + +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { asyncForEach } from "../../common/utils/asyncUtils" export const up = async () => { - const emailCustom = await EligibleTrainingsForAppointment.find({ is_lieu_formation_email_customized: true }) - .select({ - lieu_formation_email: 1, - cle_ministere_educatif: 1, - _id: 0, - }) - .lean() + const emailCustom = await getDbCollection("eligible_trainings_for_appointments") + .find( + { is_lieu_formation_email_customized: true }, + { + projection: { + lieu_formation_email: 1, + cle_ministere_educatif: 1, + _id: 0, + }, + } + ) + .toArray() await asyncForEach(emailCustom, async (custom) => { - await CustomEmailETFA.create({ email: custom.lieu_formation_email, ...custom }) + const newCustomMailETFA: ICustomEmailETFA = { + _id: new ObjectId(), + cle_ministere_educatif: custom.cle_ministere_educatif, + email: custom.lieu_formation_email as string, + } + await getDbCollection("customemailetfas").insertOne(newCustomMailETFA) }) } diff --git a/server/src/db/migrations/20240219131857-remove-etablissement-campain-webhook-array.ts b/server/src/db/migrations/20240219131857-remove-etablissement-campain-webhook-array.ts index f854d9c1dd..67aae86772 100644 --- a/server/src/db/migrations/20240219131857-remove-etablissement-campain-webhook-array.ts +++ b/server/src/db/migrations/20240219131857-remove-etablissement-campain-webhook-array.ts @@ -7,7 +7,6 @@ export const up = async (db: Db) => { $unset: { to_etablissement_emails: "", affelnet_perimetre: "" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/202402270000000-remove-user-is-anonymized.ts b/server/src/db/migrations/202402270000000-remove-user-is-anonymized.ts index 7de5dc0a8a..bb5362884c 100644 --- a/server/src/db/migrations/202402270000000-remove-user-is-anonymized.ts +++ b/server/src/db/migrations/202402270000000-remove-user-is-anonymized.ts @@ -9,7 +9,6 @@ export const up = async (db: Db) => { $unset: { is_anonymized: "" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) @@ -20,7 +19,6 @@ export const up = async (db: Db) => { $unset: { userId: "" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/202404240000000-migrate-referentiel-romes.ts b/server/src/db/migrations/202404240000000-migrate-referentiel-romes.ts index d7014ca034..5bfe6ad431 100644 --- a/server/src/db/migrations/202404240000000-migrate-referentiel-romes.ts +++ b/server/src/db/migrations/202404240000000-migrate-referentiel-romes.ts @@ -9,7 +9,6 @@ export const up = async (db: Db) => { $unset: { "jobs.$[].rome_detail": 1 }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/db/migrations/202405230000000-migrate-fix-missing-date-blacklist.ts b/server/src/db/migrations/202405230000000-migrate-fix-missing-date-blacklist.ts index 6b1ca1e5d2..f3fe4fb055 100644 --- a/server/src/db/migrations/202405230000000-migrate-fix-missing-date-blacklist.ts +++ b/server/src/db/migrations/202405230000000-migrate-fix-missing-date-blacklist.ts @@ -15,7 +15,6 @@ export const up = async (db: Db) => { $set: { created_at: DATE }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) @@ -26,7 +25,6 @@ export const up = async (db: Db) => { $set: { applicant_email: "faux_email@faux-domaine.fr" }, }, { - // @ts-expect-error bypassDocumentValidation is not properly set in @types/mongodb bypassDocumentValidation: true, } ) diff --git a/server/src/http/controllers/admin/eligibleTrainingsForAppointment.controller.ts b/server/src/http/controllers/admin/eligibleTrainingsForAppointment.controller.ts index 510a4f7c32..0de9a5cc16 100644 --- a/server/src/http/controllers/admin/eligibleTrainingsForAppointment.controller.ts +++ b/server/src/http/controllers/admin/eligibleTrainingsForAppointment.controller.ts @@ -1,8 +1,8 @@ import Boom from "boom" import { zRoutes } from "shared/index" -import { CustomEmailETFA, EligibleTrainingsForAppointment } from "../../../common/model/index" -import * as eligibleTrainingsForAppointmentService from "../../../services/eligibleTrainingsForAppointment.service" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { Server } from "../../server" /** @@ -21,7 +21,7 @@ export default (server: Server) => { async (req, res) => { const { siret } = req.params - const parameters = await EligibleTrainingsForAppointment.find({ etablissement_formateur_siret: siret }).lean() + const parameters = await getDbCollection("eligible_trainings_for_appointments").find({ etablissement_formateur_siret: siret }).toArray() if (parameters == undefined || parameters.length == 0) { throw Boom.badRequest() @@ -41,19 +41,18 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.patch["/admin/eligible-trainings-for-appointment/:id"])], }, async ({ body, params }, res) => { - console.info(body) if ("is_lieu_formation_email_customized" in body) { if (body.is_lieu_formation_email_customized) { if ("cle_ministere_educatif" in body && "lieu_formation_email" in body && body.lieu_formation_email && body.cle_ministere_educatif) { - await CustomEmailETFA.findOneAndUpdate( + await getDbCollection("customemailetfas").findOneAndUpdate( { cle_ministere_educatif: body.cle_ministere_educatif }, - { email: body.lieu_formation_email, cle_ministere_educatif: body.cle_ministere_educatif }, + { $set: { email: body.lieu_formation_email, cle_ministere_educatif: body.cle_ministere_educatif } }, { upsert: true } ) } } } - const result = await eligibleTrainingsForAppointmentService.updateParameter(params.id.toString(), body).lean() + const result = await getDbCollection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: params.id }, { $set: { ...body } }, { returnDocument: "after" }) res.send(result) } diff --git a/server/src/http/controllers/admin/etablissement.controller.ts b/server/src/http/controllers/admin/etablissement.controller.ts index 0c98a8b2c7..2892caa580 100644 --- a/server/src/http/controllers/admin/etablissement.controller.ts +++ b/server/src/http/controllers/admin/etablissement.controller.ts @@ -1,7 +1,9 @@ import Boom from "boom" +import { ObjectId } from "mongodb" import { zRoutes } from "shared/index" -import { Etablissement } from "../../../common/model/index" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { Server } from "../../server" /** @@ -18,7 +20,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.get["/admin/etablissements/siret-formateur/:siret"])], }, async ({ params }, res) => { - const etablissement = await Etablissement.findOne({ formateur_siret: params.siret }).lean() + const etablissement = await getDbCollection("etablissements").findOne({ formateur_siret: params.siret }) if (!etablissement) { throw Boom.notFound() @@ -38,7 +40,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.get["/admin/etablissements/:id"])], }, async (req, res) => { - const etablissement = await Etablissement.findById(req.params.id).lean() + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id) }) if (!etablissement) { throw Boom.notFound() @@ -58,13 +60,13 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.patch["/admin/etablissements/:id"])], }, async ({ body, params }, res) => { - const etablissement = await Etablissement.findById(params.id) + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(params.id.toString()) }) if (!etablissement) { throw Boom.notFound() } - const result = await Etablissement.findByIdAndUpdate(params.id, body).lean() + const result = await getDbCollection("etablissements").findOneAndUpdate({ _id: new ObjectId(params.id.toString()) }, { $set: body }, { returnDocument: "after" }) if (!result) { throw Boom.notFound() diff --git a/server/src/http/controllers/application.controller.ts b/server/src/http/controllers/application.controller.ts index 0f8b3b91eb..3b7679ec5e 100644 --- a/server/src/http/controllers/application.controller.ts +++ b/server/src/http/controllers/application.controller.ts @@ -1,9 +1,9 @@ import Boom from "boom" -import mongoose from "mongoose" +import { ObjectId } from "mongodb" import { oldItemTypeToNewItemType } from "shared/constants/lbaitem" import { zRoutes } from "shared/index" -import { Application } from "../../common/model/index" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { sendApplication, sendMailToApplicant } from "../../services/application.service" import { Server } from "../server" @@ -60,9 +60,9 @@ export default function (server: Server) { const { id } = req.params const { company_recruitment_intention, company_feedback, email, phone } = req.body - const application = await Application.findOneAndUpdate( - { _id: new mongoose.Types.ObjectId(id) }, - { company_recruitment_intention, company_feedback, company_feedback_date: new Date() } + const application = await getDbCollection("applications").findOneAndUpdate( + { _id: new ObjectId(id) }, + { $set: { company_recruitment_intention, company_feedback, company_feedback_date: new Date() } } ) if (!application) { @@ -92,7 +92,10 @@ export default function (server: Server) { const { id } = req.params const { company_recruitment_intention } = req.body - const application = await Application.findOneAndUpdate({ _id: new mongoose.Types.ObjectId(id) }, { company_recruitment_intention, company_feedback_date: new Date() }) + const application = await getDbCollection("applications").findOneAndUpdate( + { _id: new ObjectId(id) }, + { $set: { company_recruitment_intention, company_feedback_date: new Date() } } + ) if (!application) throw new Error("application not found") return res.status(200).send({ result: "ok" }) diff --git a/server/src/http/controllers/appointmentRequest.controller.ts b/server/src/http/controllers/appointmentRequest.controller.ts index ddf7071c18..e53bf209fc 100644 --- a/server/src/http/controllers/appointmentRequest.controller.ts +++ b/server/src/http/controllers/appointmentRequest.controller.ts @@ -1,19 +1,21 @@ import Boom from "boom" import Joi from "joi" +import { ObjectId } from "mongodb" import { EApplicantRole } from "shared/constants/rdva" import { zRoutes } from "shared/index" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" -import { getReferrerByKeyName } from "../../common/model/constants/referrers" -import { Appointment, EligibleTrainingsForAppointment, Etablissement, FormationCatalogue, User } from "../../common/model/index" import config from "../../config" import { createRdvaShortRecapToken } from "../../services/appLinks.service" import * as appointmentService from "../../services/appointment.service" import { sendCandidateAppointmentEmail, sendFormateurAppointmentEmail } from "../../services/appointment.service" import dayjs from "../../services/dayjs.service" -import { findElligibleTrainingForAppointment, findOne, getParameterByCleMinistereEducatif } from "../../services/eligibleTrainingsForAppointment.service" +import * as eligibleTrainingsForAppointmentService from "../../services/eligibleTrainingsForAppointment.service" +import { findElligibleTrainingForAppointment, getParameterByCleMinistereEducatif } from "../../services/eligibleTrainingsForAppointment.service" import mailer, { sanitizeForEmail } from "../../services/mailer.service" +import { getReferrerByKeyName } from "../../services/referrers.service" import * as users from "../../services/user.service" import { Server } from "../server" @@ -46,7 +48,7 @@ export default (server: Server) => { const referrerObj = getReferrerByKeyName(appointmentOrigin) - const eligibleTrainingsForAppointment = await findOne({ + const eligibleTrainingsForAppointment = await getDbCollection("eligible_trainings_for_appointments").findOne({ cle_ministere_educatif: cleMinistereEducatif, referrers: { $in: [referrerObj.name] }, }) @@ -86,7 +88,7 @@ export default (server: Server) => { const [createdAppointement, etablissement] = await Promise.all([ appointmentService.createAppointment({ - applicant_id: user._id, + applicant_id: user._id.toString(), cfa_recipient_email: eligibleTrainingsForAppointment.lieu_formation_email, cfa_formateur_siret: eligibleTrainingsForAppointment.etablissement_formateur_siret, applicant_message_to_cfa: applicantMessageToCfa, @@ -94,7 +96,7 @@ export default (server: Server) => { appointment_origin: referrerObj.name, cle_ministere_educatif: eligibleTrainingsForAppointment.cle_ministere_educatif, }), - Etablissement.findOne({ + getDbCollection("etablissements").findOne({ formateur_siret: eligibleTrainingsForAppointment.etablissement_formateur_siret, }), ]) @@ -124,28 +126,31 @@ export default (server: Server) => { async (req, res) => { const { appointmentId } = req.query - const appointment = await Appointment.findById(appointmentId, { cle_ministere_educatif: 1, applicant_id: 1 }).lean() + const appointment = await getDbCollection("appointments").findOne({ _id: new ObjectId(appointmentId) }, { projection: { cle_ministere_educatif: 1, applicant_id: 1 } }) if (!appointment) { throw Boom.notFound() } const [formation, user] = await Promise.all([ - EligibleTrainingsForAppointment.findOne( + eligibleTrainingsForAppointmentService.findOne( { cle_ministere_educatif: appointment.cle_ministere_educatif }, { - etablissement_formateur_raison_sociale: 1, - lieu_formation_email: 1, - _id: 0, + projection: { etablissement_formateur_raison_sociale: 1, lieu_formation_email: 1, _id: 0 }, + } + ), + getDbCollection("users").findOne( + { _id: new ObjectId(appointment.applicant_id) }, + { + projection: { + lastname: 1, + firstname: 1, + phone: 1, + email: 1, + _id: 0, + }, } - ).lean(), - User.findById(appointment.applicant_id, { - lastname: 1, - firstname: 1, - phone: 1, - email: 1, - _id: 0, - }).lean(), + ), ]) if (!formation) { @@ -172,44 +177,56 @@ export default (server: Server) => { async (req, res) => { const { appointmentId } = req.query - const appointment = await Appointment.findById(appointmentId, { - cle_ministere_educatif: 1, - applicant_id: 1, - applicant_reasons: 1, - applicant_message_to_cfa: 1, - cfa_intention_to_applicant: 1, - cfa_message_to_applicant: 1, - cfa_message_to_applicant_date: 1, - cfa_read_appointment_details_date: 1, - }).lean() + const appointment = await getDbCollection("appointments").findOne( + { _id: new ObjectId(appointmentId) }, + { + projection: { + cle_ministere_educatif: 1, + applicant_id: 1, + applicant_reasons: 1, + applicant_message_to_cfa: 1, + cfa_intention_to_applicant: 1, + cfa_message_to_applicant: 1, + cfa_message_to_applicant_date: 1, + cfa_read_appointment_details_date: 1, + }, + } + ) if (!appointment) { throw Boom.notFound() } if (!appointment.cfa_read_appointment_details_date) { - await Appointment.findByIdAndUpdate(appointmentId, { cfa_read_appointment_details_date: new Date() }) + await getDbCollection("appointments").findOneAndUpdate({ _id: new ObjectId(appointmentId) }, { $set: { cfa_read_appointment_details_date: new Date() } }) } const [formation, user] = await Promise.all([ - EligibleTrainingsForAppointment.findOne( + eligibleTrainingsForAppointmentService.findOne( { cle_ministere_educatif: appointment.cle_ministere_educatif }, { - training_intitule_long: 1, - etablissement_formateur_raison_sociale: 1, - lieu_formation_street: 1, - lieu_formation_zip_code: 1, - lieu_formation_email: 1, - lieu_formation_city: 1, + projection: { + training_intitule_long: 1, + etablissement_formateur_raison_sociale: 1, + lieu_formation_street: 1, + lieu_formation_zip_code: 1, + lieu_formation_email: 1, + lieu_formation_city: 1, + }, + } + ), + getDbCollection("users").findOne( + { _id: new ObjectId(appointment.applicant_id) }, + { + projection: { + type: 1, + lastname: 1, + firstname: 1, + phone: 1, + email: 1, + }, } - ).lean(), - User.findById(appointment.applicant_id, { - type: 1, - lastname: 1, - firstname: 1, - phone: 1, - email: 1, - }).lean(), + ), ]) if (!user) { @@ -234,7 +251,7 @@ export default (server: Server) => { await appointmentReplySchema.validateAsync(req.body, { abortEarly: false }) const { appointment_id, cfa_intention_to_applicant, cfa_message_to_applicant, cfa_message_to_applicant_date } = req.body - const appointment = await Appointment.findById(appointment_id) + const appointment = await getDbCollection("appointments").findOne({ _id: new ObjectId(appointment_id) }) if (!appointment) throw Boom.notFound() @@ -253,7 +270,7 @@ export default (server: Server) => { if (!user) throw Boom.notFound() if (cfa_intention_to_applicant === "personalised_answer") { - const formationCatalogue = cle_ministere_educatif ? await FormationCatalogue.findOne({ cle_ministere_educatif }) : undefined + const formationCatalogue = cle_ministere_educatif ? await getDbCollection("formationcatalogues").findOne({ cle_ministere_educatif }) : undefined await mailer.sendEmail({ to: user.email, @@ -271,7 +288,7 @@ export default (server: Server) => { }, }) } - await appointmentService.updateAppointment(appointment_id, { cfa_intention_to_applicant, cfa_message_to_applicant, cfa_message_to_applicant_date }) + await appointmentService.updateAppointment(appointment_id, { $set: { cfa_intention_to_applicant, cfa_message_to_applicant, cfa_message_to_applicant_date } }) res.status(200).send({ appointment_id, cfa_intention_to_applicant, cfa_message_to_applicant, cfa_message_to_applicant_date }) } ) diff --git a/server/src/http/controllers/core.controller.ts b/server/src/http/controllers/core.controller.ts index ba2275f6c2..f7ec2a3bee 100644 --- a/server/src/http/controllers/core.controller.ts +++ b/server/src/http/controllers/core.controller.ts @@ -1,31 +1,29 @@ -import mongoose from "mongoose" import { zRoutes } from "shared" import config from "@/config" +import { ensureInitialization, getMongodbClientState } from "../../common/utils/mongodbUtils" import { Server } from "../server" export const coreRoutes = (app: Server) => { app.get("/", { schema: zRoutes.get["/"] }, async (request, response) => { - const healthcheck = { - // https://mongoosejs.com/docs/5.x/docs/api/connection.html#connection_Connection-readyState - mongodb: mongoose.connection.readyState === 1, - } - - response.status(healthcheck.mongodb ? 200 : 500).send({ + ensureInitialization() + const dbState = await getMongodbClientState() + response.status(dbState === "connected" ? 200 : 500).send({ + name: "La bonne alternance", + version: config.version, env: config.env, - healthcheck, + mongo: dbState === "connected", }) }) app.get("/healthcheck", { schema: zRoutes.get["/healthcheck"] }, async (request, response) => { - const healthcheck = { - // https://mongoosejs.com/docs/5.x/docs/api/connection.html#connection_Connection-readyState - mongodb: mongoose.connection.readyState === 1, - } - - response.status(healthcheck.mongodb ? 200 : 500).send({ + ensureInitialization() + const dbState = await getMongodbClientState() + response.status(dbState === "connected" ? 200 : 500).send({ + name: "La bonne alternance", + version: config.version, env: config.env, - healthcheck, + mongo: dbState === "connected", }) }) } diff --git a/server/src/http/controllers/etablissement.controller.ts b/server/src/http/controllers/etablissement.controller.ts index be11fb60f1..2ecbe8dbfb 100644 --- a/server/src/http/controllers/etablissement.controller.ts +++ b/server/src/http/controllers/etablissement.controller.ts @@ -1,12 +1,13 @@ import Boom from "boom" import * as _ from "lodash-es" +import { ObjectId } from "mongodb" import { zRoutes } from "shared" import { referrers } from "shared/constants/referers" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sendMailCfaPremiumStart } from "@/services/etablissement.service" -import { Etablissement } from "../../common/model/index" import config from "../../config" import dayjs from "../../services/dayjs.service" import * as eligibleTrainingsForAppointmentService from "../../services/eligibleTrainingsForAppointment.service" @@ -41,7 +42,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.get["/etablissements/:id"])], }, async (req, res) => { - const etablissement = await Etablissement.findById(req.params.id, etablissementProjection).lean() + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id.toString()) }, { projection: etablissementProjection }) if (!etablissement) { throw Boom.notFound() @@ -61,7 +62,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.post["/etablissements/:id/premium/affelnet/accept"])], }, async (req, res) => { - const etablissement = await Etablissement.findById(req.params.id) + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id.toString()) }) if (!etablissement) { throw Boom.badRequest("Etablissement not found.") @@ -82,12 +83,12 @@ export default (server: Server) => { etablissement_formateur_siret: etablissement.formateur_siret, affelnet_visible: true, }), - Etablissement.findOneAndUpdate( + getDbCollection("etablissements").findOneAndUpdate( { _id: etablissement._id }, { - premium_affelnet_activation_date: dayjs().toDate(), + $set: { premium_affelnet_activation_date: dayjs().toDate() }, }, - { new: true } + { returnDocument: "after" } ), ]) @@ -130,12 +131,12 @@ export default (server: Server) => { ) const [resultAffelnet] = await Promise.all([ - Etablissement.findById(req.params.id, etablissementProjection).lean(), + await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id.toString()) }, { projection: etablissementProjection }), ...eligibleTrainingsForAppointmentsAffelnetFound.map((eligibleTrainingsForAppointment) => - eligibleTrainingsForAppointmentService.update( + eligibleTrainingsForAppointmentService.findOneAndUpdate( { _id: eligibleTrainingsForAppointment._id, lieu_formation_email: { $nin: [null, ""] } }, { - referrers: [...new Set([...eligibleTrainingsForAppointment.referrers, referrers.AFFELNET.name])], + $set: { referrers: [...new Set([...eligibleTrainingsForAppointment.referrers, referrers.AFFELNET.name])] }, } ) ), @@ -157,7 +158,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.post["/etablissements/:id/premium/accept"])], }, async (req, res) => { - const etablissement = await Etablissement.findById(req.params.id).lean() + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id.toString()) }) if (!etablissement) { throw Boom.badRequest("Etablissement not found.") @@ -181,12 +182,12 @@ export default (server: Server) => { }, parcoursup_visible: true, }), - Etablissement.findOneAndUpdate( + getDbCollection("etablissements").findOneAndUpdate( { _id: etablissement._id }, { - premium_activation_date: dayjs().toDate(), + $set: { premium_activation_date: dayjs().toDate() }, }, - { new: true } + { returnDocument: "after" } ), ]) @@ -230,12 +231,12 @@ export default (server: Server) => { ) const [result] = await Promise.all([ - Etablissement.findById(req.params.id).lean(), + await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id.toString()) }), ...eligibleTrainingsForAppointmentsParcoursupFound.map((eligibleTrainingsForAppointment) => - eligibleTrainingsForAppointmentService.update( + eligibleTrainingsForAppointmentService.findOneAndUpdate( { _id: eligibleTrainingsForAppointment._id, lieu_formation_email: { $nin: [null, ""] } }, { - referrers: [...new Set([...eligibleTrainingsForAppointment.referrers, referrers.PARCOURSUP.name])], + $set: { referrers: [...new Set([...eligibleTrainingsForAppointment.referrers, referrers.PARCOURSUP.name])] }, } ) ), @@ -257,7 +258,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.post["/etablissements/:id/premium/affelnet/refuse"])], }, async (req, res) => { - const etablissement = await Etablissement.findById(req.params.id) + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id) }) if (!etablissement) { throw Boom.badRequest("Etablissement not found.") @@ -298,14 +299,14 @@ export default (server: Server) => { }, }) - await Etablissement.findOneAndUpdate( + await await getDbCollection("etablissements").findOneAndUpdate( { _id: etablissement._id }, { - premium_affelnet_refusal_date: dayjs().toDate(), + projection: { premium_affelnet_refusal_date: dayjs().toDate() }, } ) - const etablissementAffelnetUpdated = await Etablissement.findById(req.params.id, etablissementProjection).lean() + const etablissementAffelnetUpdated = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id) }, { projection: etablissementProjection }) if (!etablissementAffelnetUpdated) { throw new Error(`unexpected: could not find etablissement with id=${req.params.id}`) } @@ -323,7 +324,7 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.post["/etablissements/:id/premium/refuse"])], }, async (req, res) => { - const etablissement = await Etablissement.findById(req.params.id) + const etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id) }) if (!etablissement) { throw Boom.badRequest("Etablissement not found.") @@ -364,14 +365,17 @@ export default (server: Server) => { }, }) - await Etablissement.findOneAndUpdate( + await getDbCollection("etablissements").findOneAndUpdate( { _id: etablissement._id }, { - premium_refusal_date: dayjs().toDate(), + $set: { premium_refusal_date: dayjs().toDate() }, } ) - const etablissementParcoursupUpdated = await Etablissement.findById(req.params.id, etablissementProjection).lean() + const etablissementParcoursupUpdated = await getDbCollection("etablissements").findOne( + { _id: new ObjectId(req.params.id.toString()) }, + { projection: etablissementProjection } + ) if (!etablissementParcoursupUpdated) { throw new Error(`unexpected: could not find etablissement with id=${req.params.id}`) } @@ -389,7 +393,10 @@ export default (server: Server) => { onRequest: [server.auth(zRoutes.post["/etablissements/:id/opt-out/unsubscribe"])], }, async (req, res) => { - let etablissement = await Etablissement.findById(req.params.id, { ...etablissementProjection, gestionnaire_email: 1 }).lean() + let etablissement = await getDbCollection("etablissements").findOne( + { _id: new ObjectId(req.params.id.toString()) }, + { projection: { ...etablissementProjection, gestionnaire_email: 1 } } + ) if (!etablissement || etablissement.optout_refusal_date) { throw Boom.notFound() @@ -421,7 +428,7 @@ export default (server: Server) => { // If opt-out is already running but user unsubscribe, disable all formations /** - * WARNING KBA 2024-02-12 : ALL REFERRERS ARE REMOVE AND ITS BAD IF PREMIUM IS AVAILABLE + * WARNING KBA 2024-02-12 : ALL REFERRERS ARE REMOVED AND ITS BAD IF PREMIUM IS AVAILABLE */ if (etablissement.optout_activation_date && dayjs(etablissement.optout_activation_date).isBefore(dayjs())) { // Disable all formations @@ -430,14 +437,19 @@ export default (server: Server) => { etablissement_formateur_siret: etablissement.formateur_siret, }, { - referrers: [], + $set: { + referrers: [], + }, } ) } - await Etablissement.findByIdAndUpdate(req.params.id, { - optout_refusal_date: dayjs().toDate(), - }) + await getDbCollection("etablissements").findOneAndUpdate( + { _id: new ObjectId(req.params.id.toString()) }, + { + $set: { optout_refusal_date: dayjs().toDate() }, + } + ) if (!etablissement.gestionnaire_email) { throw Boom.badRequest("Gestionnaire email not found") @@ -462,7 +474,7 @@ export default (server: Server) => { }, }) - etablissement = await Etablissement.findById(req.params.id, etablissementProjection).lean() + etablissement = await getDbCollection("etablissements").findOne({ _id: new ObjectId(req.params.id) }, { projection: etablissementProjection }) if (!etablissement) { throw new Error(`unexpected: could not find appointment with id=${req.params.id}`) } diff --git a/server/src/http/controllers/etablissementRecruteur.controller.ts b/server/src/http/controllers/etablissementRecruteur.controller.ts index c22886d4b4..2234901c07 100644 --- a/server/src/http/controllers/etablissementRecruteur.controller.ts +++ b/server/src/http/controllers/etablissementRecruteur.controller.ts @@ -5,7 +5,7 @@ import { RECRUITER_STATUS } from "shared/constants/recruteur" import { AccessStatus } from "shared/models/roleManagement.model" import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" -import { Cfa, Entreprise, Recruiter } from "@/common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { startSession } from "@/common/utils/session.service" import config from "@/config" import { userWithAccountToUserForToken } from "@/security/accessTokenService" @@ -79,7 +79,7 @@ export default (server: Server) => { } if (skipUpdate) { - const entrepriseOpt = await Entreprise.findOne({ siret }).lean() + const entrepriseOpt = await getDbCollection("entreprises").findOne({ siret }) if (entrepriseOpt) { return res.status(200).send(entrepriseOpt) } @@ -167,7 +167,7 @@ export default (server: Server) => { }, async (req, res) => { const { cfaId } = req.params - const cfa = await Cfa.findOne({ _id: cfaId }).lean() + const cfa = await getDbCollection("cfas").findOne({ _id: cfaId }) if (!cfa) { throw Boom.notFound(`Aucun CFA ayant pour id ${cfaId.toString()}`) } @@ -175,7 +175,9 @@ export default (server: Server) => { if (!cfa_delegated_siret) { throw Boom.internal(`inattendu : le cfa n'a pas de champ cfa_delegated_siret`) } - const entreprises = await Recruiter.find({ status: { $in: [RECRUITER_STATUS.ACTIF, RECRUITER_STATUS.EN_ATTENTE_VALIDATION] }, cfa_delegated_siret }).lean() + const entreprises = await getDbCollection("recruiters") + .find({ status: { $in: [RECRUITER_STATUS.ACTIF, RECRUITER_STATUS.EN_ATTENTE_VALIDATION] }, cfa_delegated_siret }) + .toArray() return res.status(200).send(entreprises) } ) @@ -337,7 +339,7 @@ export default (server: Server) => { throw Boom.forbidden("Votre compte est désactivé. Merci de contacter le support La bonne alternance.") } if (!isUserEmailChecked(user)) { - await validateUserWithAccountEmail(user._id.toString()) + await validateUserWithAccountEmail(user._id) } const mainRole = await getMainRoleManagement(user._id, true) if (getLastStatusEvent(mainRole?.status)?.status === AccessStatus.GRANTED) { diff --git a/server/src/http/controllers/formationRegion.controller.ts b/server/src/http/controllers/formationRegion.controller.ts index 5f6019c54f..827182d721 100644 --- a/server/src/http/controllers/formationRegion.controller.ts +++ b/server/src/http/controllers/formationRegion.controller.ts @@ -17,8 +17,6 @@ export default (server: Server) => { { schema: zRoutes.get["/v1/formationsParRegion"], config, - // TODO: AttachValidation Error ? - attachValidation: true, }, async (req, res) => { const { romes, romeDomain, caller, departement, region, diploma, options } = req.query diff --git a/server/src/http/controllers/formations.controller.ts b/server/src/http/controllers/formations.controller.ts index 4fea3d1158..37ade180be 100644 --- a/server/src/http/controllers/formations.controller.ts +++ b/server/src/http/controllers/formations.controller.ts @@ -17,7 +17,6 @@ export default (server: Server) => { { schema: zRoutes.get["/v1/formations"], config, - // TODO: AttachValidation Error ? }, async (req, res) => { const { referer } = req.headers @@ -52,7 +51,6 @@ export default (server: Server) => { { schema: zRoutes.get["/v1/formations/min"], config, - // TODO: AttachValidation Error ? }, async (req, res) => { const { referer } = req.headers @@ -87,7 +85,6 @@ export default (server: Server) => { { schema: zRoutes.get["/v1/formations/formation/:id"], config, - // TODO: AttachValidation Error ? }, async (req, res) => { const { id } = req.params diff --git a/server/src/http/controllers/jobs.controller.ts b/server/src/http/controllers/jobs.controller.ts index 824deb9ec2..82eba5160a 100644 --- a/server/src/http/controllers/jobs.controller.ts +++ b/server/src/http/controllers/jobs.controller.ts @@ -1,11 +1,11 @@ import Boom from "boom" import { IJob, JOB_STATUS, zRoutes } from "shared" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { getUserFromRequest } from "@/security/authenticationService" import { Appellation } from "@/services/rome.service.types" import { getUserWithAccountByEmail } from "@/services/userWithAccount.service" -import { Recruiter } from "../../common/model/index" import { getNearEtablissementsFromRomes } from "../../services/catalogue.service" import { ACTIVE, ANNULEE, POURVUE } from "../../services/constant.service" import dayjs from "../../services/dayjs.service" @@ -48,7 +48,7 @@ export default (server: Server) => { async (req, res) => { const { establishment_siret, email } = req.query - const establishment = await Recruiter.findOne({ establishment_siret, email }).lean() + const establishment = await getDbCollection("recruiters").findOne({ establishment_siret, email }) if (!establishment) { return res.status(400).send({ error: true, message: "Establishment not found" }) @@ -64,7 +64,6 @@ export default (server: Server) => { schema: zRoutes.get["/v1/jobs/bulk"], config, onRequest: server.auth(zRoutes.get["/v1/jobs/bulk"]), - // TODO: AttachValidation Error ? }, async (req, res) => { const { query, select, page, limit } = req.query @@ -171,7 +170,7 @@ export default (server: Server) => { custom_geo_coordinates: body.custom_geo_coordinates, custom_job_title: body.custom_job_title, is_multi_published: body.is_multi_published, - managed_by: user._id, + managed_by: user._id.toString(), } const updatedRecruiter = await createOffre(establishmentId, job) diff --git a/server/src/http/controllers/jobs.controller.v2.ts b/server/src/http/controllers/jobs.controller.v2.ts index ccdc36aea8..ccee8ad5f9 100644 --- a/server/src/http/controllers/jobs.controller.v2.ts +++ b/server/src/http/controllers/jobs.controller.v2.ts @@ -2,10 +2,10 @@ import Boom from "boom" import { IJob, ILbaItemFtJob, ILbaItemLbaJob, JOB_STATUS, assertUnreachable, zRoutes } from "shared" import { LBA_ITEM_TYPE } from "shared/constants/lbaitem" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { getUserFromRequest } from "@/security/authenticationService" import { Appellation } from "@/services/rome.service.types" -import { Recruiter } from "../../common/model/index" import { getFileSignedURL } from "../../common/utils/awsUtils" import { trackApiCall } from "../../common/utils/sendTrackingEvent" import { sentryCaptureException } from "../../common/utils/sentryUtils" @@ -51,7 +51,7 @@ export default (server: Server) => { async (req, res) => { const { establishment_siret, email } = req.query - const establishment = await Recruiter.findOne({ establishment_siret, email }).lean() + const establishment = await getDbCollection("recruiters").findOne({ establishment_siret, email }) if (!establishment) { return res.status(400).send({ error: true, message: "Establishment not found" }) diff --git a/server/src/http/controllers/jobsEtFormations.controller.ts b/server/src/http/controllers/jobsEtFormations.controller.ts index 2edce8e3e9..d27d02d3bc 100644 --- a/server/src/http/controllers/jobsEtFormations.controller.ts +++ b/server/src/http/controllers/jobsEtFormations.controller.ts @@ -20,7 +20,6 @@ export default (server: Server) => { { schema: zRoutes.get["/v1/jobsEtFormations"], config, - // TODO: AttachValidation Error ? }, async (req, res) => { const { referer } = req.headers diff --git a/server/src/http/controllers/login.controller.ts b/server/src/http/controllers/login.controller.ts index 046f9772eb..c1e66e1da9 100644 --- a/server/src/http/controllers/login.controller.ts +++ b/server/src/http/controllers/login.controller.ts @@ -2,8 +2,8 @@ import Boom from "boom" import { removeUrlsFromText } from "shared/helpers/common" import { toPublicUser, zRoutes } from "shared/index" -import { UserWithAccount } from "@/common/model" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { userWithAccountToUserForToken } from "@/security/accessTokenService" import { getUserFromRequest } from "@/security/authenticationService" import { createAuthMagicLink } from "@/services/appLinks.service" @@ -27,7 +27,7 @@ export default (server: Server) => { }, async (req, res) => { const { userId } = req.params - const user = await UserWithAccount.findOne({ _id: userId }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: userId }) if (!user) { return res.status(400).send({ error: true, reason: "UNKNOWN" }) } @@ -48,7 +48,7 @@ export default (server: Server) => { async (req, res) => { const { email } = req.body const formatedEmail = email.toLowerCase() - const user = await UserWithAccount.findOne({ email: formatedEmail }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ email: formatedEmail }) if (!user) { return res.status(400).send({ error: true, reason: "UNKNOWN" }) diff --git a/server/src/http/controllers/optout.controller.ts b/server/src/http/controllers/optout.controller.ts index 801123fe2e..24d512b702 100644 --- a/server/src/http/controllers/optout.controller.ts +++ b/server/src/http/controllers/optout.controller.ts @@ -1,9 +1,9 @@ import Boom from "boom" import { zRoutes } from "shared/index" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { getUserFromRequest } from "@/security/authenticationService" -import { Optout } from "../../common/model/index" import { Server } from "../server" export default (server: Server) => { @@ -19,7 +19,7 @@ export default (server: Server) => { throw Boom.forbidden() } - const user = await Optout.findOne({ siret: userIdentity.siret, "contacts.email": userIdentity.email }).lean() + const user = await getDbCollection("optouts").findOne({ siret: userIdentity.siret, "contacts.email": userIdentity.email }) if (!user) { return res.status(400).send({ error: true, reason: "USER_NOT_FOUND" }) diff --git a/server/src/http/controllers/partners.controller.ts b/server/src/http/controllers/partners.controller.ts index 7d7a616e0f..34d4d44011 100644 --- a/server/src/http/controllers/partners.controller.ts +++ b/server/src/http/controllers/partners.controller.ts @@ -25,7 +25,7 @@ export default (server: Server) => { }, referrers: { $in: [referrers.PARCOURSUP.name] }, }, - { parcoursup_id: 1 } + { projection: { parcoursup_id: 1 } } ) return res.send({ ids: ids.map((eligibleTrainingsForAppointment) => eligibleTrainingsForAppointment.parcoursup_id) }) diff --git a/server/src/http/controllers/unsubscribeLbaCompany.controller.ts b/server/src/http/controllers/unsubscribeLbaCompany.controller.ts index 36d66c7d68..67fd928702 100644 --- a/server/src/http/controllers/unsubscribeLbaCompany.controller.ts +++ b/server/src/http/controllers/unsubscribeLbaCompany.controller.ts @@ -1,12 +1,13 @@ -import { zRoutes } from "shared" +import { ObjectId } from "mongodb" +import { IUnsubscribedLbaCompany, zRoutes } from "shared" import { IUnsubscribeQueryResponse } from "shared/models/unsubscribeLbaCompany.model" import { asyncForEach } from "@/common/utils/asyncUtils" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { obfuscateLbaCompanyApplications } from "@/services/application.service" import { buildLbaCompanyAddress } from "@/services/lbacompany.service" -import { LbaCompany, UnsubscribedLbaCompany } from "../../common/model" import config from "../../config" import { UNSUBSCRIBE_EMAIL_ERRORS } from "../../services/constant.service" import mailer from "../../services/mailer.service" @@ -44,7 +45,7 @@ export default function (server: Server) { } } - const lbaCompaniesToUnsubscribe = await LbaCompany.find(criteria).limit(ARBITRARY_COMPANY_LIMIT).lean() + const lbaCompaniesToUnsubscribe = await getDbCollection("bonnesboites").find(criteria).limit(ARBITRARY_COMPANY_LIMIT).toArray() if (!lbaCompaniesToUnsubscribe.length) { result = { result: UNSUBSCRIBE_EMAIL_ERRORS.NON_RECONNU } @@ -54,10 +55,11 @@ export default function (server: Server) { }) result = { result: UNSUBSCRIBE_EMAIL_ERRORS.ETABLISSEMENTS_MULTIPLES, companies } } else { + const now = new Date() await asyncForEach(lbaCompaniesToUnsubscribe, async (company) => { const { siret, raison_sociale, enseigne, naf_code, naf_label, rome_codes, insee_city_code, zip_code, city, company_size, created_at, last_update_at } = company - - const unsubscribedLbaCompany = new UnsubscribedLbaCompany({ + const unsubscribedLbaCompany: IUnsubscribedLbaCompany = { + _id: new ObjectId(), siret, raison_sociale, enseigne, @@ -71,13 +73,14 @@ export default function (server: Server) { created_at, last_update_at, unsubscribe_reason: reason, - }) + unsubscribe_date: now, + } - await unsubscribedLbaCompany.save() + await getDbCollection("unsubscribedbonnesboites").insertOne(unsubscribedLbaCompany) - const lbaCompanyToUnsubscribe = await LbaCompany.findOne({ siret }) + const lbaCompanyToUnsubscribe = await getDbCollection("bonnesboites").findOne({ siret }) if (lbaCompanyToUnsubscribe) { - await lbaCompanyToUnsubscribe.remove() + await getDbCollection("bonnesboites").deleteOne({ _id: lbaCompanyToUnsubscribe._id }) } if (reason === "OPPOSITION") { diff --git a/server/src/http/controllers/user.controller.ts b/server/src/http/controllers/user.controller.ts index 008d86c618..1cd68f3cfa 100644 --- a/server/src/http/controllers/user.controller.ts +++ b/server/src/http/controllers/user.controller.ts @@ -1,4 +1,5 @@ import Boom from "boom" +import { ObjectId } from "mongodb" import { BusinessErrorCodes } from "shared/constants/errorCodes" import { CFA, OPCOS, VALIDATION_UTILISATEUR } from "shared/constants/recruteur" import { IJob, IRecruiter, getUserStatus, parseEnumOrError, zRoutes } from "shared/index" @@ -12,8 +13,8 @@ import { getUserFromRequest } from "@/security/authenticationService" import { modifyPermissionToUser, roleToUserType } from "@/services/roleManagement.service" import { activateUser, createSuperUser, getUserWithAccountByEmail, validateUserWithAccountEmail } from "@/services/userWithAccount.service" -import { Cfa, Entreprise, Recruiter, RoleManagement, UserWithAccount } from "../../common/model/index" import { getStaticFilePath } from "../../common/utils/getStaticFilePath" +import { getDbCollection } from "../../common/utils/mongodbUtils" import config from "../../config" import { ENTREPRISE, RECRUITER_STATUS } from "../../services/constant.service" import { @@ -45,7 +46,7 @@ export default (server: Server) => { }, async (req, res) => { const userFromRequest = getUserFromRequest(req, zRoutes.get["/user/opco"]).value - const opcoRole = await RoleManagement.findOne({ authorized_type: AccessEntityType.OPCO, user_id: userFromRequest._id.toString() }).lean() + const opcoRole = await getDbCollection("rolemanagements").findOne({ authorized_type: AccessEntityType.OPCO, user_id: userFromRequest._id }) if (!opcoRole) { throw Boom.forbidden("pas de role opco") } @@ -85,9 +86,9 @@ export default (server: Server) => { }, async (req, res) => { const { userId } = req.params - const user = await UserWithAccount.findById(userId).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: new ObjectId(userId) }) if (!user) throw Boom.notFound(`user with id=${userId} not found`) - const role = await RoleManagement.findOne({ user_id: userId, authorized_type: { $in: [AccessEntityType.ADMIN, AccessEntityType.OPCO] } }).lean() + const role = await getDbCollection("rolemanagements").findOne({ user_id: new ObjectId(userId), authorized_type: { $in: [AccessEntityType.ADMIN, AccessEntityType.OPCO] } }) return res.status(200).send({ ...user, role: role ?? undefined }) } ) @@ -123,7 +124,7 @@ export default (server: Server) => { throw Boom.badRequest("L'email est déjà utilisé", { error: BusinessErrorCodes.EMAIL_ALREADY_EXISTS }) } if (opco) { - const entreprise = await Entreprise.findOneAndUpdate({ siret }, { opco }).lean() + const entreprise = await getDbCollection("entreprises").findOneAndUpdate({ siret }, { $set: { opco, updatedAt: new Date() } }, { returnDocument: "after" }) if (!entreprise) { throw Boom.badRequest(`pas d'entreprise ayant le siret ${siret}`) } @@ -162,25 +163,27 @@ export default (server: Server) => { const requestUser = getUserFromRequest(req, zRoutes.get["/user/:userId/organization/:organizationId"]).value if (!requestUser) throw Boom.badRequest() const { userId } = req.params - const role = await RoleManagement.findOne({ - user_id: userId, + const role = await getDbCollection("rolemanagements").findOne({ + user_id: new ObjectId(userId), // TODO à activer lorsque le frontend passe organizationId correctement // authorized_id: organizationId, - }).lean() + }) if (!role) { throw Boom.badRequest("role not found") } - const user = await UserWithAccount.findOne({ _id: userId }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: new ObjectId(userId) }) if (!user) { throw Boom.badRequest("user not found") } const type = roleToUserType(role) + if (!type) { throw Boom.internal("user type not found") } + let organization: ICFA | IEntreprise | null = null if (type === CFA || type === ENTREPRISE) { - organization = await (type === CFA ? Cfa : Entreprise).findOne({ _id: role.authorized_id }).lean() + organization = await getDbCollection(type === CFA ? "cfas" : "entreprises").findOne({ _id: new ObjectId(role.authorized_id) }) if (!organization) { throw Boom.internal(`inattendu : impossible de trouver l'organization avec id=${role.authorized_id}`) } @@ -196,10 +199,11 @@ export default (server: Server) => { const userRecruteur = userAndRoleAndOrganizationToUserRecruteur(user, role, organization, formulaire) - const opcoOrAdminRole = await RoleManagement.findOne({ + const opcoOrAdminRole = await getDbCollection("rolemanagements").findOne({ user_id: requestUser._id, authorized_type: { $in: [AccessEntityType.ADMIN, AccessEntityType.OPCO] }, - }).lean() + }) + if (opcoOrAdminRole && getLastStatusEvent(opcoOrAdminRole.status)?.status === AccessStatus.GRANTED) { const userIds = userRecruteur.status.flatMap(({ user }) => (user ? [user] : [])) const users = await getUsersFromIds(userIds) @@ -277,10 +281,10 @@ export default (server: Server) => { const { userId, organizationId } = req.params const requestUser = getUserFromRequest(req, zRoutes.put["/user/:userId/organization/:organizationId/permission"]).value if (!requestUser) throw Boom.badRequest() - const user = await UserWithAccount.findOne({ _id: userId }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: userId }) if (!user) throw Boom.badRequest() - const roles = await RoleManagement.find({ user_id: userId }).lean() + const roles = await getDbCollection("rolemanagements").find({ user_id: userId }).toArray() if (roles.length !== 1) { throw Boom.internal(`inattendu : attendu 1 role, ${roles.length} roles trouvés pour user id=${userId}`) } @@ -362,7 +366,7 @@ export default (server: Server) => { } // validate user email addresse - await validateUserWithAccountEmail(user._id.toString()) + await validateUserWithAccountEmail(user._id) await sendWelcomeEmailToUserRecruteur(user) return res.status(200).send({}) } @@ -400,15 +404,15 @@ export default (server: Server) => { throw Boom.notFound("user not found") } const { siret } = req.params - const entrepriseOpt = await Entreprise.findOne({ siret }).lean() + const entrepriseOpt = await getDbCollection("entreprises").findOne({ siret }) if (entrepriseOpt) { - await RoleManagement.deleteOne({ user_id: userOpt._id, authorized_id: entrepriseOpt._id.toString(), authorized_type: AccessEntityType.ENTREPRISE }) + await getDbCollection("rolemanagements").deleteOne({ user_id: userOpt._id, authorized_id: entrepriseOpt._id.toString(), authorized_type: AccessEntityType.ENTREPRISE }) } - const cfaOpt = await Cfa.findOne({ siret }).lean() + const cfaOpt = await getDbCollection("cfas").findOne({ siret }) if (cfaOpt) { - await RoleManagement.deleteOne({ user_id: userOpt._id, authorized_id: cfaOpt._id.toString(), authorized_type: AccessEntityType.CFA }) + await getDbCollection("rolemanagements").deleteOne({ user_id: userOpt._id, authorized_id: cfaOpt._id.toString(), authorized_type: AccessEntityType.CFA }) } - await Recruiter.deleteOne({ establishment_siret: siret, managed_by: userOpt._id.toString() }) + await getDbCollection("recruiters").deleteOne({ establishment_siret: siret, managed_by: userOpt._id.toString() }) return res.status(200).send({}) } ) diff --git a/server/src/http/sentry.ts b/server/src/http/sentry.ts index b3f0876d92..d128bc0108 100644 --- a/server/src/http/sentry.ts +++ b/server/src/http/sentry.ts @@ -1,16 +1,19 @@ +/** + * KBA : to be updated when switching to mongoDB + * url : https://github.com/mission-apprentissage/api-apprentissage/blob/105fdf0aadadf1fc5bf2d8184a8825a64204fd17/server/src/services/sentry/sentry.ts + */ + +// @ts-nocheck import fastifySentryPlugin from "@immobiliarelabs/fastify-sentry" -import { ExtraErrorData } from "@sentry/integrations" import * as Sentry from "@sentry/node" import { FastifyRequest } from "fastify" import { assertUnreachable } from "shared/utils" -import { mongooseInstance } from "@/common/mongodb" -import { startSentryPerfRecording } from "@/common/utils/sentryUtils" import config from "@/config" import { Server } from "./server" -function getOptions() { +function getOptions(): Sentry.NodeOptions { return { dsn: config.serverSentryDsn, tracesSampleRate: config.env === "production" ? 0.1 : 1.0, @@ -18,13 +21,17 @@ function getOptions() { environment: config.env, release: config.version, enabled: config.env !== "local", - integrations: [new Sentry.Integrations.Http({ tracing: true }), new Sentry.Integrations.Mongo({ useMongoose: true }), new ExtraErrorData({ depth: 8 })], + integrations: [ + new Sentry.Integrations.Http({ tracing: true }), + new Sentry.Integrations.Mongo({ useMongoose: false }), + Sentry.extraErrorDataIntegration({ depth: 16 }), + Sentry.captureConsoleIntegration({ levels: ["error"] }), + ], } } export function initSentryProcessor(): void { - Sentry.init(getOptions() as any) - registerMongoosePlugin() + Sentry.init(getOptions()) } export async function closeSentry(): Promise { @@ -90,53 +97,4 @@ export function initSentryFastify(app: Server) { } app.register(fastifySentryPlugin, options) - registerMongoosePlugin() -} - -function registerMongoosePlugin() { - // Tracing.Integrations.Mongo doesn't track properly db operations - // see https://github.com/getsentry/sentry-javascript/issues/4078 - mongooseInstance.plugin((s) => { - // List of all events can be found here https://mongoosejs.com/docs/5.x/docs/middleware.html - const ops = [ - "aggregate", - "count", - "countDocuments", - "deleteOne", - "deleteMany", - "estimatedDocumentCount", - "find", - "findOne", - "findOneAndDelete", - "findOneAndRemove", - "findOneAndReplace", - "findOneAndUpdate", - "insertMany", - "remove", - "replaceOne", - "save", - "update", - "updateOne", - "updateMany", - "validate", - ] - - // For each event we will start perf recording on pre event and stop it on post event - ops.forEach((op) => { - // We need to store callback returned from startSentryPerfRecording to be called in post event - // Because queries can run in parallel we need to execute the proper callback on post event - // Finally we need a WeakMap to be sure we release memory in case of any failure. - const queryToCbMap = new WeakMap() - s.pre(op, function () { - // this reference the current query according to mongoose plugin API - queryToCbMap.set(this, startSentryPerfRecording("mongoose", op)) - }) - s.post(op, function () { - // Execute the associated callback if found - queryToCbMap.get(this)?.() - // Make sure to remove the query from the map - queryToCbMap.delete(this) - }) - }) - }) } diff --git a/server/src/jobs/anonymization/anonumizeAppointments.ts b/server/src/jobs/anonymization/anonumizeAppointments.ts index 71781c7004..7a44e4046e 100644 --- a/server/src/jobs/anonymization/anonumizeAppointments.ts +++ b/server/src/jobs/anonymization/anonumizeAppointments.ts @@ -1,5 +1,5 @@ import { logger } from "../../common/logger" -import { Appointment } from "../../common/model/index" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { notifyToSlack } from "../../common/utils/slackUtils" const anonymizeAppointments = async () => { @@ -8,29 +8,31 @@ const anonymizeAppointments = async () => { const lastYear = new Date() lastYear.setFullYear(lastYear.getFullYear() - 1) - await Appointment.aggregate([ - { - $match: { created_at: { $lte: lastYear } }, - }, - { - $project: { - applicant_id: 1, - cfa_intention_to_applicant: 1, - cfa_message_to_applicant_date: 1, - cfa_gestionnaire_siret: 1, - cfa_formateur_siret: 1, - cfa_read_appointment_details_date: 1, - appointment_origin: 1, - cle_ministere_educatif: 1, - created_at: 1, + await getDbCollection("appointments") + .aggregate([ + { + $match: { created_at: { $lte: lastYear } }, }, - }, - { - $merge: "anonymizedappointments", - }, - ]) + { + $project: { + applicant_id: 1, + cfa_intention_to_applicant: 1, + cfa_message_to_applicant_date: 1, + cfa_gestionnaire_siret: 1, + cfa_formateur_siret: 1, + cfa_read_appointment_details_date: 1, + appointment_origin: 1, + cle_ministere_educatif: 1, + created_at: 1, + }, + }, + { + $merge: "anonymizedappointments", + }, + ]) + .toArray() - const res = await Appointment.deleteMany({ created_at: { $lte: lastYear } }) + const res = await getDbCollection("appointments").deleteMany({ created_at: { $lte: lastYear } }) return res.deletedCount } diff --git a/server/src/jobs/anonymization/anonymizeIndividual.ts b/server/src/jobs/anonymization/anonymizeIndividual.ts index f32b0ec2c8..1c101b3d05 100644 --- a/server/src/jobs/anonymization/anonymizeIndividual.ts +++ b/server/src/jobs/anonymization/anonymizeIndividual.ts @@ -1,105 +1,121 @@ +import { ObjectId } from "mongodb" + +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { AnonymizedUser, Application, Recruiter, User, UserWithAccount } from "../../common/model/index" -const anonimizeUserWithAccount = (_id: string) => - UserWithAccount.aggregate([ - { - $match: { _id }, - }, - { - $project: { - last_action_date: 1, - origin: 1, - status: 1, +const anonimizeUserWithAccount = (_id: ObjectId) => + getDbCollection("userswithaccounts") + .aggregate([ + { + $match: { _id }, + }, + { + $project: { + last_action_date: 1, + origin: 1, + status: 1, + }, }, - }, - { - $merge: "anonymizeduser2s", - }, - ]) + { + $merge: "anonymizeduserswithaccounts", + }, + ]) + .toArray() -const anonimizeRecruiterByUserId = (userId: string) => - Recruiter.aggregate([ - { - $match: { "jobs.managed_by": userId }, - }, - { - $project: { - establishment_id: 1, - establishment_raison_sociale: 1, - establishment_enseigne: 1, - establishment_siret: 1, - address_detail: 1, - address: 1, - geo_coordinates: 1, - is_delegated: 1, - cfa_delegated_siret: 1, - jobs: 1, - origin: 1, - opco: 1, - idcc: 1, - status: 1, - naf_code: 1, - naf_label: 1, - establishment_size: 1, - establishment_creation_date: 1, +const anonimizeRecruiterByUserId = (userId: ObjectId) => + getDbCollection("recruiters") + .aggregate([ + { + $match: { "jobs.managed_by": userId }, + }, + { + $project: { + establishment_id: 1, + establishment_raison_sociale: 1, + establishment_enseigne: 1, + establishment_siret: 1, + address_detail: 1, + address: 1, + geo_coordinates: 1, + is_delegated: 1, + cfa_delegated_siret: 1, + jobs: 1, + origin: 1, + opco: 1, + idcc: 1, + status: 1, + naf_code: 1, + naf_label: 1, + establishment_size: 1, + establishment_creation_date: 1, + }, + }, + { + $merge: "anonymizedrecruiteurs", }, - }, - { - $merge: "anonymizedrecruiteurs", - }, - ]) + ]) + .toArray() -const deleteRecruiter = (query) => Recruiter.deleteMany(query) -const deleteUserWithAccount = (query) => UserWithAccount.deleteMany(query) +const deleteRecruiter = (query) => getDbCollection("recruiters").deleteMany(query) +const deleteUserWithAccount = (query) => getDbCollection("userswithaccounts").deleteMany(query) -const anonymizeApplication = async (_id: string) => { - await Application.aggregate([ - { - $match: { _id }, - }, - { - $project: { - company_recruitment_intention: 1, - company_feedback_date: 1, - company_siret: 1, - company_naf: 1, - job_origin: 1, - job_id: 1, - caller: 1, - created_at: 1, +const anonymizeApplication = async (_id: ObjectId) => { + await getDbCollection("applications") + .aggregate([ + { + $match: { _id }, }, - }, - { - $merge: "anonymizedapplications", - }, - ]) + { + $project: { + company_recruitment_intention: 1, + company_feedback_date: 1, + company_siret: 1, + company_naf: 1, + job_origin: 1, + job_id: 1, + caller: 1, + created_at: 1, + }, + }, + { + $merge: "anonymizedapplications", + }, + ]) + .toArray() - await Application.deleteOne({ _id }) + await getDbCollection("applications").deleteOne({ _id }) logger.info(`Anonymized application ${_id}`) } -const anonymizeUser = async (_id: string) => { - const user = await User.findOne({ _id }).lean() +const anonymizeUser = async (_id: ObjectId) => { + await getDbCollection("users") + .aggregate([ + { + $match: { _id }, + }, + { + $project: { + _id: 1, + type: 1, + role: 1, + last_action_date: 1, + }, + }, + { + $merge: "anonymizedusers", + }, + ]) + .toArray() - if (user) { - await AnonymizedUser.create({ - userId: user._id, - type: user.type, - role: user.role, - last_action_date: user.last_action_date, - }) - await User.deleteOne({ _id }) + await getDbCollection("users").deleteOne({ _id }) - logger.info(`Anonymized user ${_id}`) - } else { - logger.info(`User not found ${_id}`) - } + logger.info(`Anonymized user ${_id}`) } -const anonymizeUserWithAccountAndRecruiter = async (userId: string) => { - const user = await UserWithAccount.findById(userId) +const anonymizeUserWithAccountAndRecruiter = async (userId: ObjectId) => { + const user = await getDbCollection("userswithaccounts").findOne({ _id: userId }) if (!user) { throw new Error("Anonymize user not found") } @@ -107,7 +123,7 @@ const anonymizeUserWithAccountAndRecruiter = async (userId: string) => { await Promise.all([deleteUserWithAccount({ _id: userId }), deleteRecruiter({ "jobs.managed_by": userId })]) } -export async function anonymizeIndividual({ collection, id }: { collection: string; id: string }): Promise { +export async function anonymizeIndividual({ collection, id }: { collection: string; id: ObjectId }): Promise { switch (collection) { case "applications": { await anonymizeApplication(id) diff --git a/server/src/jobs/anonymization/anonymizeOldApplications.ts b/server/src/jobs/anonymization/anonymizeOldApplications.ts index 7859c7381b..d4770fce6a 100644 --- a/server/src/jobs/anonymization/anonymizeOldApplications.ts +++ b/server/src/jobs/anonymization/anonymizeOldApplications.ts @@ -1,5 +1,5 @@ import { logger } from "../../common/logger" -import { Application } from "../../common/model/index" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { notifyToSlack } from "../../common/utils/slackUtils" const anonymizeApplications = async () => { @@ -10,28 +10,30 @@ const anonymizeApplications = async () => { const matchCondition = { created_at: { $lte: lastYear } } - await Application.aggregate([ - { - $match: matchCondition, - }, - { - $project: { - company_recruitment_intention: 1, - company_feedback_date: 1, - company_siret: 1, - company_naf: 1, - job_origin: 1, - job_id: 1, - caller: 1, - created_at: 1, + await getDbCollection("applications") + .aggregate([ + { + $match: matchCondition, }, - }, - { - $merge: "anonymizedapplications", - }, - ]) + { + $project: { + company_recruitment_intention: 1, + company_feedback_date: 1, + company_siret: 1, + company_naf: 1, + job_origin: 1, + job_id: 1, + caller: 1, + created_at: 1, + }, + }, + { + $merge: "anonymizedapplications", + }, + ]) + .toArray() - const res = await Application.deleteMany(matchCondition) + const res = await getDbCollection("applications").deleteMany(matchCondition) return res.deletedCount } diff --git a/server/src/jobs/anonymization/anonymizeUserRecruteurs.ts b/server/src/jobs/anonymization/anonymizeUserRecruteurs.ts index 9c3392cf10..51119fd90d 100644 --- a/server/src/jobs/anonymization/anonymizeUserRecruteurs.ts +++ b/server/src/jobs/anonymization/anonymizeUserRecruteurs.ts @@ -1,62 +1,67 @@ import dayjs from "dayjs" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { Recruiter, UserWithAccount } from "../../common/model/index" import { notifyToSlack } from "../../common/utils/slackUtils" const anonymize = async () => { const fromDate = dayjs().subtract(2, "years").toDate() const userWithAccountQuery = { $or: [{ last_action_date: { $lte: fromDate } }, { last_action_date: null, createdAt: { $lte: fromDate } }] } - const usersToAnonymize = await UserWithAccount.find(userWithAccountQuery).lean() - const userIds = usersToAnonymize.map(({ _id }) => _id.toString()) + const usersToAnonymize = await getDbCollection("userswithaccounts").find(userWithAccountQuery).toArray() + const userIds = usersToAnonymize.map(({ _id }) => _id) const recruiterQuery = { "jobs.managed_by": { $in: userIds } } - await UserWithAccount.aggregate([ - { - $match: userWithAccountQuery, - }, - { - $project: { - last_action_date: 1, - origin: 1, - status: 1, + await getDbCollection("userswithaccounts") + .aggregate([ + { + $match: userWithAccountQuery, + }, + { + $project: { + last_action_date: 1, + origin: 1, + status: 1, + }, + }, + { + $merge: "anonymizeduserswithaccounts", + }, + ]) + .toArray() + await getDbCollection("recruiters") + .aggregate([ + { + $match: recruiterQuery, + }, + { + $project: { + establishment_id: 1, + establishment_raison_sociale: 1, + establishment_enseigne: 1, + establishment_siret: 1, + address_detail: 1, + address: 1, + geo_coordinates: 1, + is_delegated: 1, + cfa_delegated_siret: 1, + jobs: 1, + origin: 1, + opco: 1, + idcc: 1, + status: 1, + naf_code: 1, + naf_label: 1, + establishment_size: 1, + establishment_creation_date: 1, + }, }, - }, - { - $merge: "anonymizeduserwithaccounts", - }, - ]) - await Recruiter.aggregate([ - { - $match: recruiterQuery, - }, - { - $project: { - establishment_id: 1, - establishment_raison_sociale: 1, - establishment_enseigne: 1, - establishment_siret: 1, - address_detail: 1, - address: 1, - geo_coordinates: 1, - is_delegated: 1, - cfa_delegated_siret: 1, - jobs: 1, - origin: 1, - opco: 1, - idcc: 1, - status: 1, - naf_code: 1, - naf_label: 1, - establishment_size: 1, - establishment_creation_date: 1, + { + $merge: "anonymizedrecruiteurs", }, - }, - { - $merge: "anonymizedrecruiteurs", - }, - ]) - const { deletedCount: recruiterCount } = await Recruiter.deleteMany(recruiterQuery) - const { deletedCount: userWithAccountCount } = await UserWithAccount.deleteMany(userWithAccountQuery) + ]) + .toArray() + const { deletedCount: recruiterCount } = await getDbCollection("recruiters").deleteMany(recruiterQuery) + const { deletedCount: userWithAccountCount } = await getDbCollection("userswithaccounts").deleteMany(userWithAccountQuery) return { userWithAccountCount, recruiterCount } } diff --git a/server/src/jobs/applications/fixApplications.ts b/server/src/jobs/applications/fixApplications.ts index 24680fe22b..8b39da629f 100644 --- a/server/src/jobs/applications/fixApplications.ts +++ b/server/src/jobs/applications/fixApplications.ts @@ -1,18 +1,21 @@ import { cleanEmail } from "shared/helpers/common" import { logger } from "@/common/logger" -import { db } from "@/common/mongodb" + +import { getDbCollection } from "../../common/utils/mongodbUtils" const removeOrReplaceCharsInDB = async () => { logger.info("Nettoyage des adresses emails mal formées dans applications.applicant_email") const charsRegex = /[^a-zA-Z0-9@_.+-]/ - const applicantsCursor = await db.collection("applications").find({ applicant_email: { $regex: charsRegex } }) + const applicantsCursor = await getDbCollection("applications") + .find({ applicant_email: { $regex: charsRegex } }) + .toArray() for await (const application of applicantsCursor) { const applicant_email = cleanEmail(application.applicant_email) if (applicant_email !== application.applicant_email) { - await db.collection("applications").updateOne({ _id: application._id }, { $set: { applicant_email } }) + await getDbCollection("applications").updateOne({ _id: application._id }, { $set: { applicant_email } }) } } } @@ -20,7 +23,7 @@ const removeOrReplaceCharsInDB = async () => { export default async function fixApplications() { await removeOrReplaceCharsInDB() - await db.collection("applications").updateMany( + await getDbCollection("applications").updateMany( { company_naf: null }, { $set: { company_naf: "" } }, { @@ -28,7 +31,7 @@ export default async function fixApplications() { } ) - await db.collection("applications").updateMany( + await getDbCollection("applications").updateMany( { job_title: null }, { $set: { job_title: "" } }, { diff --git a/server/src/jobs/crons_actions.ts b/server/src/jobs/crons_actions.ts index 7f7a1c5803..30c7902377 100644 --- a/server/src/jobs/crons_actions.ts +++ b/server/src/jobs/crons_actions.ts @@ -1,11 +1,10 @@ import cronParser from "cron-parser" -import mongoose from "mongoose" -import { IInternalJobsCron } from "@/common/model/schema/internalJobs/internalJobs.types" -import { db } from "@/common/mongodb" +import { IInternalJobsCron } from "@/common/model/internalJobs.types" import config from "@/config" import { getLoggerWithContext } from "../common/logger" +import { getDbCollection } from "../common/utils/mongodbUtils" import { createJobCron, createJobCronTask, createJobSimple, findJob, findJobs, updateJob } from "./job.actions" import { CRONS } from "./jobs" @@ -26,8 +25,8 @@ export async function cronsInit() { } logger.info(`Crons - initialise crons in DB`) - await db.collection("internalJobs").deleteMany({ type: "cron" }) - await db.collection("internalJobs").deleteMany({ + await getDbCollection("internalJobs").deleteMany({ type: "cron" }) + await getDbCollection("internalJobs").deleteMany({ status: { $in: ["pending", "will_start"] }, type: "cron_task", }) @@ -68,7 +67,7 @@ export async function cronsScheduler(): Promise { scheduled_for: next.toDate(), }) - await updateJob(new mongoose.Types.ObjectId(cron._id), { + await updateJob(cron._id, { scheduled_for: next.toDate(), }) } diff --git a/server/src/jobs/database/fixDiffusibleCompanies.ts b/server/src/jobs/database/fixDiffusibleCompanies.ts index 7564b8de6a..303053ad87 100644 --- a/server/src/jobs/database/fixDiffusibleCompanies.ts +++ b/server/src/jobs/database/fixDiffusibleCompanies.ts @@ -1,12 +1,11 @@ -import { ILbaCompany, IRecruiter, JOB_STATUS } from "shared" +import { IRecruiter, JOB_STATUS } from "shared" import { EDiffusibleStatus } from "shared/constants/diffusibleStatus" import { RECRUITER_STATUS } from "shared/constants/recruteur" import { IEntreprise } from "shared/models/entreprise.model" import { AccessEntityType } from "shared/models/roleManagement.model" import { logger } from "@/common/logger" -import { Entreprise, Recruiter, RoleManagement } from "@/common/model" -import { db } from "@/common/mongodb" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { getDiffusionStatus } from "@/services/etablissement.service" const ANONYMIZED = "anonymized" @@ -14,7 +13,7 @@ const FAKE_GEOLOCATION = "0,0" const fixLbaCompanies = async () => { logger.info(`Fixing diffusible lba companies`) - const lbaCompanies: AsyncIterable = await db.collection("bonnesboites").find({}) + const lbaCompanies = getDbCollection("bonnesboites").find({}) let count = 0 let deletedCount = 0 @@ -28,7 +27,7 @@ const fixLbaCompanies = async () => { const isDiffusible = await getDiffusionStatus(lbaCompany.siret) if (isDiffusible !== EDiffusibleStatus.DIFFUSIBLE) { - await db.collection("bonnesboites").deleteOne({ siret: lbaCompany.siret }) + await getDbCollection("bonnesboites").deleteOne({ siret: lbaCompany.siret }) deletedCount++ } } catch (err) { @@ -55,19 +54,19 @@ const deactivateRecruiter = async (recruiter: IRecruiter) => { job.job_status = JOB_STATUS.ACTIVE ? JOB_STATUS.ANNULEE : job.job_status } - await Recruiter.updateOne({ _id: recruiter._id }, { $set: { ...recruiter } }) + await getDbCollection("recruiters").updateOne({ _id: recruiter._id }, { $set: { ...recruiter, updatedAt: new Date() } }) } const deactivateEntreprise = async (entreprise: IEntreprise) => { const { siret } = entreprise console.info("deactivating non diffusible entreprise : ", siret) - await Entreprise.deleteOne({ _id: entreprise._id }) - await RoleManagement.deleteMany({ authorized_type: AccessEntityType.ENTREPRISE, authorized_id: entreprise._id.toString() }) + await getDbCollection("entreprises").deleteOne({ _id: entreprise._id }) + await getDbCollection("rolemanagements").deleteMany({ authorized_type: AccessEntityType.ENTREPRISE, authorized_id: entreprise._id.toString() }) } const fixRecruiters = async () => { logger.info(`Fixing diffusible recruiters and offers`) - const recruiters: AsyncIterable = await db.collection("recruiters").find({}) + const recruiters = getDbCollection("recruiters").find({}) let count = 0 let deactivatedCount = 0 @@ -92,7 +91,7 @@ const fixRecruiters = async () => { } } - const entreprises: AsyncIterable = await db.collection("entreprises").find({}) + const entreprises = getDbCollection("entreprises").find({}) count = 0 deactivatedCount = 0 @@ -132,56 +131,3 @@ export async function fixDiffusibleCompanies(payload: { collection_list?: string await fixRecruiters() } } - -export async function checkDiffusibleCompanies(): Promise { - logger.info(`Checking diffusible sirets`) - const sirets: AsyncIterable<{ _id: string }> = await db.collection("tmp_siret").find({}) - - let count = 0 - let nonDiffusibleCount = 0 - let partiellementDiffusibleCount = 0 - let unavailableCount = 0 - let notFoundCount = 0 - let errorCount = 0 - - for await (const { _id } of sirets) { - if (count % 100 === 0) { - logger.info( - `${count} sirets checked. ${partiellementDiffusibleCount} partDiff. ${unavailableCount} indisp. ${notFoundCount} non trouvé. ${nonDiffusibleCount} nonDiff. ${errorCount} errors` - ) - } - count++ - try { - const isDiffusible = await getDiffusionStatus(_id) - - switch (isDiffusible) { - case EDiffusibleStatus.NON_DIFFUSIBLE: { - nonDiffusibleCount++ - break - } - case EDiffusibleStatus.PARTIELLEMENT_DIFFUSIBLE: { - partiellementDiffusibleCount++ - break - } - case EDiffusibleStatus.UNAVAILABLE: { - unavailableCount++ - break - } - case EDiffusibleStatus.NOT_FOUND: { - notFoundCount++ - break - } - default: - } - } catch (err) { - errorCount++ - console.error(err) - break - } - } - logger.info( - `FIN : ${count} companies checked. ${partiellementDiffusibleCount} partDiff. ${unavailableCount} indisp. ${notFoundCount} non trouvé. ${nonDiffusibleCount} nonDiff. ${errorCount} errors` - ) - - logger.info(`Checking sirets done`) -} diff --git a/server/src/jobs/database/obfuscateCollections.ts b/server/src/jobs/database/obfuscateCollections.ts index 53a8762b60..3a2d4a5f88 100644 --- a/server/src/jobs/database/obfuscateCollections.ts +++ b/server/src/jobs/database/obfuscateCollections.ts @@ -1,43 +1,26 @@ import { randomUUID } from "crypto" -import { Model } from "mongoose" -import { getLastStatusEvent, IEmailBlacklist, IUser, IUserRecruteur } from "shared" -import { AUTHTYPE, VALIDATION_UTILISATEUR } from "shared/constants/recruteur" +import { getLastStatusEvent } from "shared" +import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur" +import { CollectionName } from "shared/models/models" import { AccessEntityType, AccessStatus } from "shared/models/roleManagement.model" import { UserEventType } from "shared/models/userWithAccount.model" import { logger } from "@/common/logger" -import { - AnonymizedApplication, - ApiCalls, - Application, - Appointment, - EligibleTrainingsForAppointment, - eligibleTrainingsForAppointmentHistory, - EmailBlacklist, - Etablissement, - FormationCatalogue, - LbaCompany, - RecruteurLbaUpdateEvent, - Optout, - Recruiter, - RoleManagement, -} from "@/common/model/index" -import { Pagination } from "@/common/model/schema/_shared/mongoose-paginate" -import { db } from "@/common/mongodb" +import { getDbCollection } from "@/common/utils/mongodbUtils" import config from "@/config" const fakeEmail = "faux_email@faux-domaine-compagnie.com" -async function reduceModel(model: Model | Pagination, limit = 20000) { - logger.info(`reducing collection ${model.collection.name} to ${limit} latest documents`) +async function reduceModel(model: CollectionName, limit = 20000) { + logger.info(`reducing collection ${model} to ${limit} latest documents`) try { const aggregationPipeline = [{ $match: {} }, { $sort: { created_at: -1 } }, { $skip: limit }, { $limit: 1 }, { $project: { _id: 0, minDate: "$created_at" } }] - const result = await model.aggregate(aggregationPipeline) + const result = await getDbCollection(model).aggregate(aggregationPipeline).toArray() if (result.length) { - await model.deleteMany({ created_at: { $lt: result[0].minDate } }) + await getDbCollection(model).deleteMany({ created_at: { $lt: result[0].minDate } }) } } catch (err) { logger.error("Error reducing collection", err) @@ -46,90 +29,98 @@ async function reduceModel(model: Model | Pagination, limit = 20000) { const obfuscateApplications = async () => { logger.info(`obfuscating applications`) - await Application.updateMany( + await getDbCollection("applications").updateMany( {}, { - applicant_email: "faux_email@faux-domaine.fr", - applicant_phone: "0601010106", - applicant_last_name: "nom_famille", - applicant_first_name: "prenom", - applicant_attachment_name: "titre_cv.pdf", - applicant_message_to_company: "Cher recruteur, embauchez moi ...", - company_feedback: "Cher candidat ...", - company_email: fakeEmail, + $set: { + applicant_email: "faux_email@faux-domaine.fr", + applicant_phone: "0601010106", + applicant_last_name: "nom_famille", + applicant_first_name: "prenom", + applicant_attachment_name: "titre_cv.pdf", + applicant_message_to_company: "Cher recruteur, embauchez moi ...", + company_feedback: "Cher candidat ...", + company_email: fakeEmail, + }, } ) } const obfuscateEmailBlackList = async () => { logger.info(`obfuscating email blacklist`) - const emails: AsyncIterable = await db.collection("emailblacklists").find({}) + const emails = getDbCollection("emailblacklists").find({}) for await (const ebl of emails) { const email = getFakeEmail() const replacement = { $set: { email } } - await db.collection("emailblacklists").findOneAndUpdate({ _id: ebl._id }, replacement) + await getDbCollection("emailblacklists").findOneAndUpdate({ _id: ebl._id }, replacement) } logger.info(`obfuscating email blacklist done`) } const obfuscateAppointments = async () => { logger.info(`obfuscating appointments`) - await Appointment.updateMany( + await getDbCollection("appointments").updateMany( {}, { - cfa_message_to_applicant: "Réponse du cfa ...", - applicant_message_to_cfa: "Message du candidat ...", - cfa_recipient_email: fakeEmail, + $set: { + cfa_message_to_applicant: "Réponse du cfa ...", + applicant_message_to_cfa: "Message du candidat ...", + cfa_recipient_email: fakeEmail, + }, } ) } const obfuscateLbaCompanies = async () => { logger.info(`obfuscating lbacompanies`) - await LbaCompany.updateMany( + await getDbCollection("bonnesboites").updateMany( {}, { - email: fakeEmail, - phone: "0601010106", + $set: { + email: fakeEmail, + phone: "0601010106", + }, } ) } const obfuscateElligibleTrainingsForAppointment = async () => { logger.info(`obfuscating elligible trainings for appointments`) - await EligibleTrainingsForAppointment.updateMany( + await getDbCollection("eligible_trainings_for_appointments").updateMany( {}, { - lieu_formation_email: fakeEmail, + $set: { lieu_formation_email: fakeEmail }, } ) - await eligibleTrainingsForAppointmentHistory.updateMany( + await getDbCollection("eligible_trainings_for_appointments_history").updateMany( {}, { - lieu_formation_email: fakeEmail, + $set: { lieu_formation_email: fakeEmail }, } ) } const obfuscateEtablissements = async () => { logger.info(`obfuscating etablissements`) - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( {}, { - gestionnaire_email: fakeEmail, + $set: { gestionnaire_email: fakeEmail }, } ) } const obfuscateFormations = async () => { logger.info(`obfuscating formations`) - await FormationCatalogue.updateMany( + await getDbCollection("formationcatalogues").updateMany( {}, { - email: fakeEmail, - etablissement_gestionnaire_courriel: fakeEmail, - etablissement_formateur_courriel: fakeEmail, - num_tel: "0601010106", + $set: { + email: fakeEmail, + etablissement_gestionnaire_courriel: fakeEmail, + etablissement_formateur_courriel: fakeEmail, + num_tel: "0601010106", + }, } ) } @@ -137,7 +128,7 @@ const obfuscateFormations = async () => { const getFakeEmail = () => `${randomUUID()}@faux-domaine.fr` const keepSpecificUser = async (email: string, type: AccessEntityType) => { - const role = await RoleManagement.findOne({ authorized_type: type }).lean() + const role = await getDbCollection("rolemanagements").findOne({ authorized_type: type }) const replacement = { $set: { email }, $push: { @@ -150,10 +141,10 @@ const keepSpecificUser = async (email: string, type: AccessEntityType) => { }, } if (role) { - await db.collection("userswithaccounts").findOneAndUpdate({ _id: role.user_id }, replacement) + await getDbCollection("userswithaccounts").findOneAndUpdate({ _id: role.user_id }, replacement) if (getLastStatusEvent(role.status)?.status !== AccessStatus.GRANTED) { - await RoleManagement.findOneAndUpdate( + await getDbCollection("rolemanagements").findOneAndUpdate( { _id: role._id }, { $push: { @@ -175,40 +166,14 @@ const ADMIN_EMAIL = "admin-recette@beta.gouv.fr" const obfuscateRecruiter = async () => { logger.info(`obfuscating recruiters`) - const users: AsyncIterable = db.collection("userrecruteurs").find({}) - for await (const user of users) { - const replacement = { $set: { email: getFakeEmail(), phone: "0601010106", last_name: "nom_famille", first_name: "prenom" } } - - switch (user.type) { - case AUTHTYPE.ENTREPRISE: { - await Promise.all([ - db.collection("userrecruteurs").findOneAndUpdate({ _id: user._id }, replacement), - db.collection("recruiters").findOneAndUpdate({ establishment_id: user.establishment_id }, replacement), - ]) - break - } - case AUTHTYPE.CFA: { - await Promise.all([ - db.collection("userrecruteurs").findOneAndUpdate({ _id: user._id }, replacement), - db.collection("recruiters").updateMany({ cfa_delegated_siret: user.establishment_siret }, replacement), - ]) - break - } - - default: { - await db.collection("userrecruteurs").findOneAndUpdate({ _id: user._id }, replacement) - break - } - } - } - - const remainingUsers: AsyncIterable = db.collection("recruiters").find({ first_name: { $ne: "prenom" } }) + const remainingUsers = getDbCollection("recruiters").find({ first_name: { $ne: "prenom" } }) for await (const user of remainingUsers) { const replacement = { $set: { email: getFakeEmail(), phone: "0601010106", last_name: "nom_famille", first_name: "prenom" } } - db.collection("recruiters").findOneAndUpdate({ _id: user._id }, replacement) + getDbCollection("recruiters").findOneAndUpdate({ _id: user._id }, replacement) } - const recruitersWithDelegations = Recruiter.find({ "jobs.delegations.0": { $exists: true } }) + const recruitersWithDelegations = getDbCollection("recruiters").find({ "jobs.delegations.0": { $exists: true } }) + for await (const recruiter of recruitersWithDelegations) { let shouldSave = false if (recruiter.jobs) { @@ -222,7 +187,7 @@ const obfuscateRecruiter = async () => { }) } if (shouldSave) { - await Recruiter.updateOne({ _id: recruiter._id }, { $set: { ...recruiter } }) + await getDbCollection("recruiters").updateOne({ _id: recruiter._id }, { $set: { ...recruiter, updatedAt: new Date() } }) } } @@ -231,11 +196,11 @@ const obfuscateRecruiter = async () => { const obfuscateUser = async () => { logger.info(`obfuscating users`) - const users: AsyncIterable = await db.collection("users").find({}) + const users = getDbCollection("users").find({}) for await (const user of users) { const email = getFakeEmail() const replacement = { $set: { email, phone: "0601010106", lastname: "nom_famille", firstname: "prenom" } } - await db.collection("users").findOneAndUpdate({ _id: user._id }, replacement) + await getDbCollection("users").findOneAndUpdate({ _id: user._id }, replacement) } logger.info(`obfuscating users done`) @@ -243,13 +208,13 @@ const obfuscateUser = async () => { const obfuscateUsersWithAccounts = async () => { logger.info(`obfuscating userswithaccounts`) - const users: AsyncIterable = await db.collection("userswithaccounts").find({}) + const users = getDbCollection("userswithaccounts").find({}) for await (const user of users) { const email = getFakeEmail() const replacement = { $set: { email, phone: "0601010106", last_name: "nom_famille", first_name: "prenom" }, } - await db.collection("userswithaccounts").findOneAndUpdate({ _id: user._id }, replacement) + await getDbCollection("userswithaccounts").findOneAndUpdate({ _id: user._id }, replacement) } logger.info(`obfuscating userswithaccounts done`) @@ -272,11 +237,11 @@ export async function obfuscateCollections(): Promise { // prévention :) return } - await reduceModel(ApiCalls, 20000) - await reduceModel(Application, 50000) - await reduceModel(AnonymizedApplication, 5000) - await reduceModel(Appointment, 10000) - await reduceModel(EmailBlacklist, 100) + await reduceModel("apicalls", 20000) + await reduceModel("applications", 50000) + // await reduceModel("anonymizedapplications", 5000) // TODO + await reduceModel("appointments", 10000) + await reduceModel("emailblacklists", 100) await obfuscateApplications() await obfuscateEmailBlackList() await obfuscateAppointments() @@ -287,6 +252,6 @@ export async function obfuscateCollections(): Promise { await obfuscateRecruiter() await obfuscateUser() await obfuscateUsersWithAccounts() - await Optout.deleteMany({}) - await RecruteurLbaUpdateEvent.deleteMany({}) + await getDbCollection("optouts").deleteMany({}) + // TODO recruteur LBA update event deleteMany ?? } diff --git a/server/src/jobs/database/recreateIndexes.ts b/server/src/jobs/database/recreateIndexes.ts new file mode 100644 index 0000000000..4f355c0728 --- /dev/null +++ b/server/src/jobs/database/recreateIndexes.ts @@ -0,0 +1,15 @@ +import { createIndexes, dropIndexes } from "@/common/utils/mongodbUtils" + +import { logger } from "../../common/logger" + +logger + +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/jobs/database/removeVersionKeyFromAllCollections.ts b/server/src/jobs/database/removeVersionKeyFromAllCollections.ts deleted file mode 100644 index 983f6e0aa6..0000000000 --- a/server/src/jobs/database/removeVersionKeyFromAllCollections.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { mongooseInstance } from "../../common/mongodb" - -/** - * Remove the "__v" key from all collections. - */ -export const removeVersionKeyFromAllCollections = async () => { - const db = mongooseInstance.connection - - for (const collection of Object.keys(db.collections)) { - // @ts-ignore - await db.collection(collection).updateMany( - {}, - { - $unset: { __v: "" }, - } - ) - } -} diff --git a/server/src/jobs/database/schemaValidation.ts b/server/src/jobs/database/schemaValidation.ts new file mode 100644 index 0000000000..602406660b --- /dev/null +++ b/server/src/jobs/database/schemaValidation.ts @@ -0,0 +1,24 @@ +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/jobs/database/temp/fixCollections.ts b/server/src/jobs/database/temp/fixCollections.ts deleted file mode 100644 index d393cec00a..0000000000 --- a/server/src/jobs/database/temp/fixCollections.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { z } from "zod" - -import { Appointment, Optout, User } from "../../../common/model" -import { asyncForEach } from "../../../common/utils/asyncUtils" - -const fixOptoutContactList = async () => { - const optouts = await Optout.find({}).lean() - - await asyncForEach(optouts, async ({ contacts, _id }) => { - await asyncForEach(contacts, async (contact) => { - if (!z.string().email().safeParse(contact.email).success) { - await Optout.findByIdAndUpdate(_id, { $pull: { contacts: { email: contact.email } } }) - } - }) - }) -} - -const fixUserMissingType = async () => await User.updateMany({ type: { $exists: false } }, { $set: { type: "etudiant" } }) - -const fixUserEmail = async () => { - const users = await User.find({}).lean() - await asyncForEach(users, async (user) => { - if (!z.string().email().safeParse(user.email).success) { - await Appointment.findOneAndDelete({ applicant_id: user._id.toString() }) - await User.findByIdAndDelete(user._id) - } - }) -} - -export const fixCollections = async () => { - await fixOptoutContactList() - await fixUserMissingType() - await fixUserEmail() -} diff --git a/server/src/jobs/database/temp/fixRDVACollections.ts b/server/src/jobs/database/temp/fixRDVACollections.ts deleted file mode 100644 index 23bae6f953..0000000000 --- a/server/src/jobs/database/temp/fixRDVACollections.ts +++ /dev/null @@ -1,26 +0,0 @@ -import dayjs from "shared/helpers/dayjs" - -import { EmailBlacklist, Etablissement } from "../../../common/model" - -// SIRET number that does not comply with LUHN algorythm in etablissements collection -const SIRET_TO_REMOVE_FROM_ETABLISSEMENT = [ - "13002799900132", - "99999999999920", - "78144401300000", - "33778063900000", - "78151651300000", - "19331424200000", - "19330028200000", - "19470020900017", - "52407208900175", -] - -const DATE = dayjs().toDate() - -const removeObsoleteEtablissement = async () => await Etablissement.deleteMany({ formateur_siret: { $in: SIRET_TO_REMOVE_FROM_ETABLISSEMENT } }) -const addMissingDateFieldToEmailBlacklist = async () => await EmailBlacklist.updateMany({ created_at: { $exists: false } }, { $set: { created_at: DATE } }) - -export const fixRDVACollections = async () => { - await removeObsoleteEtablissement() - await addMissingDateFieldToEmailBlacklist() -} diff --git a/server/src/jobs/database/validateModels.ts b/server/src/jobs/database/validateModels.ts deleted file mode 100644 index 2949fb25ba..0000000000 --- a/server/src/jobs/database/validateModels.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { captureException } from "@sentry/node" -import { Model } from "mongoose" -import { - ZApiCall, - ZApplication, - ZAppointment, - ZCredential, - ZDiplomesMetiers, - ZDomainesMetiers, - ZEligibleTrainingsForAppointmentSchema, - ZEmailBlacklist, - ZEtablissement, - ZGeoLocation, - ZLbaCompany, - ZLbaLegacyCompany, - ZOptout, - ZRecruiter, - ZReferentielOnisep, - ZReferentielOpco, - ZUnsubscribeOF, - ZUnsubscribedLbaCompany, - ZUser, - zFormationCatalogueSchema, -} from "shared/models" -import { zCFA } from "shared/models/cfa.model" -import { ZEntreprise } from "shared/models/entreprise.model" -import { ZRoleManagement } from "shared/models/roleManagement.model" -import { ZUserWithAccount } from "shared/models/userWithAccount.model" -import { ZodType } from "zod" - -import { logger } from "@/common/logger" -import { - ApiCalls, - Application, - Appointment, - AppointmentDetailed, - Cfa, - Credential, - DiplomesMetiers, - DomainesMetiers, - EligibleTrainingsForAppointment, - EmailBlacklist, - Entreprise, - Etablissement, - FormationCatalogue, - GeoLocation, - LbaCompany, - LbaCompanyLegacy, - Optout, - Recruiter, - ReferentielOnisep, - ReferentielOpco, - RoleManagement, - UnsubscribeOF, - UnsubscribedLbaCompany, - User, - UserWithAccount, -} from "@/common/model/index" -import { Pagination } from "@/common/model/schema/_shared/mongoose-paginate" - -async function validateModel(model: Model | Pagination, z: ZodType) { - const collectionName = model.collection.name - const cursor = model.find({}).lean() - - let totalCount = 0 - let count = 0 - const errorStats: Record = {} - for await (const doc of cursor) { - try { - totalCount++ - z.parse(doc) - } catch (err) { - count++ - - if (err && typeof err === "object" && "issues" in err && Array.isArray(err.issues)) { - err.issues.forEach(({ code, path, expected, received, message }) => { - const pointPath = path.join(".") - const key = `${pointPath}: code=${code}, expected=${expected}, received=${received}, message=${message}` - const oldCount = errorStats[key] ?? 0 - errorStats[key] = oldCount + 1 - }) - } - } - } - - if (count > 0) { - const errorMessage = `Found ${count}/${totalCount} invalid document for ${collectionName} - Error cases: - ${Object.entries(errorStats) - .map(([message, count]) => `${count} : ${message}`) - .join("\n")} - ` - logger.error(errorMessage) - captureException(new Error(errorMessage)) - } else { - logger.info(`All documents ${totalCount} for ${collectionName} are valid`) - } -} - -export async function validateModels(): Promise { - // TODO: Create Zod for missing models - await validateModel(ApiCalls, ZApiCall) - await validateModel(Application, ZApplication) - await validateModel(Appointment, ZAppointment) - await validateModel(AppointmentDetailed, ZAppointment) - await validateModel(Credential, ZCredential) - await validateModel(DiplomesMetiers, ZDiplomesMetiers) - await validateModel(DomainesMetiers, ZDomainesMetiers) - await validateModel(EligibleTrainingsForAppointment, ZEligibleTrainingsForAppointmentSchema) - await validateModel(EmailBlacklist, ZEmailBlacklist) - await validateModel(Etablissement, ZEtablissement) - await validateModel(FormationCatalogue, zFormationCatalogueSchema) - await validateModel(GeoLocation, ZGeoLocation) - // // await validateModel(InternalJobs, ZInternalJobs) - await validateModel(LbaCompany, ZLbaCompany) - await validateModel(LbaCompanyLegacy, ZLbaLegacyCompany) - // await validateModel(Opco, ZOpco) - await validateModel(Optout, ZOptout) - await validateModel(Recruiter, ZRecruiter) - await validateModel(ReferentielOnisep, ZReferentielOnisep) - await validateModel(User, ZUser) - await validateModel(ReferentielOpco, ZReferentielOpco) - await validateModel(UnsubscribeOF, ZUnsubscribeOF) - await validateModel(UnsubscribedLbaCompany, ZUnsubscribedLbaCompany) - await validateModel(Entreprise, ZEntreprise) - await validateModel(Cfa, zCFA) - await validateModel(UserWithAccount, ZUserWithAccount) - await validateModel(RoleManagement, ZRoleManagement) -} diff --git a/server/src/jobs/diplomesMetiers/updateDiplomesMetiers.ts b/server/src/jobs/diplomesMetiers/updateDiplomesMetiers.ts index 0a2ca1de7c..aaa4213f7f 100644 --- a/server/src/jobs/diplomesMetiers/updateDiplomesMetiers.ts +++ b/server/src/jobs/diplomesMetiers/updateDiplomesMetiers.ts @@ -1,9 +1,9 @@ -import { ZDiplomesMetiersNew } from "shared/models" +import { ZDiplomesMetiers } from "shared/models" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { initializeCacheDiplomas } from "@/services/metiers.service" import { logger } from "../../common/logger" -import { DiplomesMetiers, FormationCatalogue } from "../../common/model/index" const motsIgnores = ["a", "au", "aux", "l", "le", "la", "les", "d", "de", "du", "des", "et", "en"] const diplomesMetiers = {} @@ -56,7 +56,9 @@ const filterWrongRomes = (formation) => { } const getIntitulesFormations = async () => { - const intitulesFormations = await FormationCatalogue.find({}, { _id: 0, intitule_long: 1, rome_codes: 1, rncp_code: 1 }).lean() + const intitulesFormations = await getDbCollection("formationcatalogues") + .find({}, { projection: { _id: 0, intitule_long: 1, rome_codes: 1, rncp_code: 1 } }) + .toArray() for (const formation of intitulesFormations) { filterWrongRomes(formation) @@ -81,7 +83,7 @@ export default async function () { logger.info(" -- Start of DiplomesMetiers initializer -- ") logger.info(`Clearing diplomesmetiers...`) - await DiplomesMetiers.deleteMany({}) + await getDbCollection("diplomesmetiers").deleteMany({}) logger.info(`Début traitement`) @@ -91,9 +93,9 @@ export default async function () { diplomesMetiers[k].acronymes_intitule = buildAcronyms(diplomesMetiers[k].intitule_long) if (diplomesMetiers[k]?.codes_romes?.length) { - const parsedDiplomeMetier = ZDiplomesMetiersNew.safeParse(diplomesMetiers[k]) + const parsedDiplomeMetier = ZDiplomesMetiers.safeParse(diplomesMetiers[k]) if (parsedDiplomeMetier.success) { - await new DiplomesMetiers(parsedDiplomeMetier.data).save() + await getDbCollection("diplomesmetiers").insertOne(parsedDiplomeMetier.data) } else { logger.error(`Mauvais format diplomesmetier pour le diplôme ${diplomesMetiers[k].intitule_long}`) } diff --git a/server/src/jobs/domainesMetiers/updateDomainesMetiers.ts b/server/src/jobs/domainesMetiers/updateDomainesMetiers.ts index 09791bb6dc..78ded0d20a 100644 --- a/server/src/jobs/domainesMetiers/updateDomainesMetiers.ts +++ b/server/src/jobs/domainesMetiers/updateDomainesMetiers.ts @@ -1,19 +1,19 @@ import fs from "fs" import path from "path" +import { ObjectId } from "mongodb" import { oleoduc } from "oleoduc" -import { ZDomainesMetiers } from "shared/models" +import { IDomainesMetiers, ZDomainesMetiers } from "shared/models" import { removeAccents } from "shared/utils" import XLSX from "xlsx" -import { IDomainesMetiers } from "@/common/model/schema/domainesmetiers/domainesmetiers.types" import { initializeCacheMetiers } from "@/services/metiers.service" import __dirname from "../../common/dirname" import { logger } from "../../common/logger" -import { DomainesMetiers } from "../../common/model/index" import { getFileFromS3Bucket } from "../../common/utils/awsUtils" import { readXLSXFile } from "../../common/utils/fileUtils" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { sentryCaptureException } from "../../common/utils/sentryUtils" import { createAssetsFolder } from "../lbb/lbaCompaniesUtils" @@ -35,7 +35,7 @@ export default async function (optionalFileName?: string) { await downloadAndSaveFile(optionalFileName) logger.info(`Clearing domainesmetiers...`) - await DomainesMetiers.deleteMany({}) + await getDbCollection("domainesmetiers").deleteMany({}) const workbookDomainesMetiers = readXLSXFile(FILEPATH) @@ -99,7 +99,9 @@ export default async function (optionalFileName?: string) { // cas de la ligne sur laquelle se trouve le nom du métier qui va marquer l'insertion d'une ligne dans la db step = 1 + const now = new Date() const paramsDomaineMetier: IDomainesMetiers = { + _id: new ObjectId(), domaine: domaine, domaine_sans_accent_computed: removeAccents(domaine), sous_domaine: metier, @@ -123,8 +125,8 @@ export default async function (optionalFileName?: string) { intitules_fap_sans_accent_computed: [...new Set(libellesFAPs)].map(removeAccents), sous_domaine_onisep: sousDomainesOnisep, sous_domaine_onisep_sans_accent_computed: sousDomainesOnisep.map(removeAccents), - created_at: new Date(), - last_update_at: new Date(), + created_at: now, + last_update_at: now, } if (codesROMEs.length > 15) { @@ -134,7 +136,7 @@ export default async function (optionalFileName?: string) { const parsedDomaineMetier = ZDomainesMetiers.safeParse(paramsDomaineMetier) if (parsedDomaineMetier.success) { - await new DomainesMetiers(parsedDomaineMetier.data).save() + await getDbCollection("domainesmetiers").insertOne(paramsDomaineMetier) } else { logger.error(`Erreur non bloquante : mauvais format de domaines metiers domaine=${paramsDomaineMetier.domaine} - sous_domaine=${paramsDomaineMetier.sous_domaine}`) } diff --git a/server/src/jobs/formationsCatalogue/formationsCatalogue.ts b/server/src/jobs/formationsCatalogue/formationsCatalogue.ts index 292ae72524..3fa981db9b 100644 --- a/server/src/jobs/formationsCatalogue/formationsCatalogue.ts +++ b/server/src/jobs/formationsCatalogue/formationsCatalogue.ts @@ -1,10 +1,11 @@ +import { ObjectId } from "mongodb" import { oleoduc, writeData } from "oleoduc" import { zFormationCatalogueSchemaNew } from "shared/models" import { convertStringCoordinatesToGeoPoint } from "@/common/utils/geolib" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { logger } from "../../common/logger" -import { FormationCatalogue } from "../../common/model/index" import { sentryCaptureException } from "../../common/utils/sentryUtils" import { notifyToSlack } from "../../common/utils/slackUtils" import { countFormations, getAllFormationsFromCatalogue } from "../../services/catalogue.service" @@ -29,7 +30,7 @@ const importFormations = async () => { formation.lieu_formation_geopoint = convertStringCoordinatesToGeoPoint(formation.lieu_formation_geo_coordonnees) const parsedFormation = zFormationCatalogueSchemaNew.parse(formation) - await FormationCatalogue.collection.insertOne(parsedFormation) + await getDbCollection("formationcatalogues").insertOne({ _id: new ObjectId(), ...parsedFormation }) stats.created++ } catch (e) { logger.error("Erreur enregistrement de formation", e) @@ -62,7 +63,7 @@ export const importCatalogueFormationJob = async () => { return } - await FormationCatalogue.deleteMany({}) + await getDbCollection("formationcatalogues").deleteMany({}) const stats = await importFormations() diff --git a/server/src/jobs/formationsCatalogue/updateParcoursupAndAffelnetInfoOnFormationCatalogue.ts b/server/src/jobs/formationsCatalogue/updateParcoursupAndAffelnetInfoOnFormationCatalogue.ts index aab90a99eb..ba91bc5daa 100644 --- a/server/src/jobs/formationsCatalogue/updateParcoursupAndAffelnetInfoOnFormationCatalogue.ts +++ b/server/src/jobs/formationsCatalogue/updateParcoursupAndAffelnetInfoOnFormationCatalogue.ts @@ -1,15 +1,16 @@ import { IFormationCatalogue } from "shared" -import { db } from "@/common/mongodb" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { logger } from "../../common/logger" -import { FormationCatalogue } from "../../common/model/index" import { asyncForEach } from "../../common/utils/asyncUtils" import { getParcoursupAndAffelnetPerimetreFromCatalogueME } from "../../services/catalogue.service" export const updateParcoursupAndAffelnetInfoOnFormationCatalogue = async () => { logger.info("--- update formation catalogue data --- start") - const formations = await FormationCatalogue.find({}).select({ cle_ministere_educatif: 1 }).lean() + const formations = await getDbCollection("formationcatalogues") + .find({}, { projection: { _id: 0, cle_ministere_educatif: 1 } }) + .toArray() const catalogueMinistereEducatif = await getParcoursupAndAffelnetPerimetreFromCatalogueME() if (!catalogueMinistereEducatif) return @@ -19,12 +20,10 @@ export const updateParcoursupAndAffelnetInfoOnFormationCatalogue = async () => { if (found) { const { parcoursup_perimetre_prise_rdv, affelnet_perimetre_prise_rdv, parcoursup_id } = found - await db - .collection("formationcatalogues") - .updateOne( - { cle_ministere_educatif: formation.cle_ministere_educatif }, - { $set: { affelnet_visible: affelnet_perimetre_prise_rdv, parcoursup_visible: parcoursup_perimetre_prise_rdv, parcoursup_id } } - ) + await getDbCollection("formationcatalogues").updateOne( + { cle_ministere_educatif: formation.cle_ministere_educatif }, + { $set: { affelnet_visible: affelnet_perimetre_prise_rdv, parcoursup_visible: parcoursup_perimetre_prise_rdv, parcoursup_id } } + ) } }) logger.info("--- update formation catalogue data --- end") diff --git a/server/src/jobs/job.actions.ts b/server/src/jobs/job.actions.ts index d4e9ef01fd..7572661d6d 100644 --- a/server/src/jobs/job.actions.ts +++ b/server/src/jobs/job.actions.ts @@ -1,12 +1,14 @@ -import type { ObjectId, MatchKeysAndValues, FilterQuery, FindOneOptions } from "mongodb" +import { Filter, FindOptions, MatchKeysAndValues, ObjectId } from "mongodb" -import { IInternalJobs, IInternalJobsCron, IInternalJobsCronTask, IInternalJobsSimple } from "@/common/model/schema/internalJobs/internalJobs.types" -import { db } from "@/common/mongodb" +import { IInternalJobs, IInternalJobsCron, IInternalJobsCronTask, IInternalJobsSimple } from "@/common/model/internalJobs.types" + +import { getDbCollection } from "../common/utils/mongodbUtils" type CreateJobSimpleParams = Pick export const createJobSimple = async ({ name, payload, scheduled_for = new Date(), sync = false }: CreateJobSimpleParams): Promise => { - const job: Omit = { + const job: IInternalJobsSimple = { + _id: new ObjectId(), name, type: "simple", status: sync ? "will_start" : "pending", @@ -16,14 +18,15 @@ export const createJobSimple = async ({ name, payload, scheduled_for = new Date( scheduled_for, sync, } - const { insertedId: _id } = await db.collection("internalJobs").insertOne(job) - return { ...job, _id } as IInternalJobsSimple + await getDbCollection("internalJobs").insertOne(job) + return job } type CreateJobCronParams = Pick export const createJobCron = async ({ name, cron_string, scheduled_for = new Date(), sync = false }: CreateJobCronParams): Promise => { - const job: Omit = { + const job: IInternalJobsCron = { + _id: new ObjectId(), name, type: "cron", status: sync ? "will_start" : "pending", @@ -33,14 +36,15 @@ export const createJobCron = async ({ name, cron_string, scheduled_for = new Dat scheduled_for, sync, } - const { insertedId: _id } = await db.collection("internalJobs").insertOne(job) - return { ...job, _id } + await getDbCollection("internalJobs").insertOne(job) + return job } type CreateJobCronTaskParams = Pick export const createJobCronTask = async ({ name, scheduled_for }: CreateJobCronTaskParams): Promise => { - const job: Omit = { + const job: IInternalJobsCronTask = { + _id: new ObjectId(), name, type: "cron_task", status: "pending", @@ -49,21 +53,21 @@ export const createJobCronTask = async ({ name, scheduled_for }: CreateJobCronTa scheduled_for, sync: false, } - const { insertedId: _id } = await db.collection("internalJobs").insertOne(job) - return { ...job, _id } + await getDbCollection("internalJobs").insertOne(job) + return job } -export const findJob = async (filter: FilterQuery, options?: FindOneOptions): Promise => { - return await db.collection("internalJobs").findOne(filter, options) +export const findJob = async (filter: Filter, options?: FindOptions): Promise => { + return await getDbCollection("internalJobs").findOne(filter, options) } -export const findJobs = async (filter: FilterQuery, options?: FindOneOptions): Promise => { - return await db.collection("internalJobs").find(filter, options).toArray() +export const findJobs = async (filter: Filter, options?: FindOptions): Promise => { + return await getDbCollection("internalJobs").find(filter, options).toArray() } /** * Mise à jour d'un job */ export const updateJob = async (_id: ObjectId, data: MatchKeysAndValues) => { - return db.collection("internalJobs").updateOne({ _id }, { $set: { ...data, updated_at: new Date() } }) + return getDbCollection("internalJobs").updateOne({ _id }, { $set: { ...data, updated_at: new Date() } }) } diff --git a/server/src/jobs/jobs.ts b/server/src/jobs/jobs.ts index af9087fb1d..e72109934c 100644 --- a/server/src/jobs/jobs.ts +++ b/server/src/jobs/jobs.ts @@ -1,5 +1,6 @@ -import { createMongoDBIndexes } from "@/common/model" -import { IInternalJobsCronTask, IInternalJobsSimple } from "@/common/model/schema/internalJobs/internalJobs.types" +import { ObjectId } from "mongodb" + +import { IInternalJobsCronTask, IInternalJobsSimple } from "@/common/model/internalJobs.types" import { create as createMigration, status as statusMigration, up as upMigration } from "@/jobs/migrations/migrations" import { getLoggerWithContext } from "../common/logger" @@ -11,9 +12,8 @@ import { anonimizeUsers } from "./anonymization/anonymizeUserRecruteurs" import fixApplications from "./applications/fixApplications" import { cronsInit, cronsScheduler } from "./crons_actions" import { obfuscateCollections } from "./database/obfuscateCollections" -import { removeVersionKeyFromAllCollections } from "./database/removeVersionKeyFromAllCollections" -import { fixRDVACollections } from "./database/temp/fixRDVACollections" -import { validateModels } from "./database/validateModels" +import { recreateIndexes } from "./database/recreateIndexes" +import { validateModels } from "./database/schemaValidation" import updateDiplomesMetiers from "./diplomesMetiers/updateDiplomesMetiers" import updateDomainesMetiers from "./domainesMetiers/updateDomainesMetiers" import updateDomainesMetiersFile from "./domainesMetiers/updateDomainesMetiersFile" @@ -27,9 +27,7 @@ import { annuleFormulaire } from "./lba_recruteur/formulaire/annuleFormulaire" import { fixJobExpirationDate } from "./lba_recruteur/formulaire/fixJobExpirationDate" import { fixJobType } from "./lba_recruteur/formulaire/fixJobType" import { fixRecruiterDataValidation } from "./lba_recruteur/formulaire/fixRecruiterDataValidation" -import { removeIsDelegatedFromJobs } from "./lba_recruteur/formulaire/misc/removeIsDelegatedFromJobs" import { repiseGeocoordinates } from "./lba_recruteur/formulaire/misc/repriseGeocoordinates" -import { resendDelegationEmailWithAccessToken } from "./lba_recruteur/formulaire/misc/sendDelegationEmailWithSecuredToken" import { updateAddressDetailOnRecruitersCollection } from "./lba_recruteur/formulaire/misc/updateAddressDetailOnRecruitersCollection" import { updateMissingStartDate } from "./lba_recruteur/formulaire/misc/updateMissingStartDate" import { relanceFormulaire } from "./lba_recruteur/formulaire/relanceFormulaire" @@ -55,13 +53,11 @@ import { inviteEtablissementParcoursupToPremium } from "./rdv/inviteEtablissemen import { inviteEtablissementParcoursupToPremiumFollowUp } from "./rdv/inviteEtablissementParcoursupToPremiumFollowUp" import { inviteEtablissementToOptOut } from "./rdv/inviteEtablissementToOptOut" import { fixDuplicateUsers } from "./rdv/oneTimeJob/fixDuplicateUsers" -import { repriseEmailRdvs } from "./rdv/oneTimeJob/repriseEmailsRdv" import { premiumActivatedReminder } from "./rdv/premiumActivatedReminder" import { premiumInviteOneShot } from "./rdv/premiumInviteOneShot" import { removeDuplicateEtablissements } from "./rdv/removeDuplicateEtablissements" import { syncEtablissementDates } from "./rdv/syncEtablissementDates" import { syncEtablissementsAndFormations } from "./rdv/syncEtablissementsAndFormations" -import { importFichesRomeV4 } from "./seed/ficheMetierRomev4/ficheMetierRomev4" import { importReferentielRome } from "./seed/referentielRome/referentielRome" import updateBrevoBlockedEmails from "./updateBrevoBlockedEmails/updateBrevoBlockedEmails" import { controlApplications } from "./verifications/controlApplications" @@ -224,6 +220,8 @@ export async function runJob(job: IInternalJobsCronTask | IInternalJobsSimple): return CronsMap[job.name].handler() } switch (job.name) { + case "recreate:indexes": + return recreateIndexes() case "lbajobs:export:s3": return exportLbaJobsToS3() case "sync:etablissement:dates": @@ -234,12 +232,8 @@ export async function runJob(job: IInternalJobsCronTask | IInternalJobsSimple): return runGarbageCollector() case "anonymize:appointments": return anonymizeOldAppointments() - case "recruiters:delegations": // Temporaire, doit tourner une fois en production - return resendDelegationEmailWithAccessToken() case "fix:duplicate:users": // Temporaire, doit tourner une fois en production return fixDuplicateUsers() - case "migration:correctionRDVA": // Temporaire, doit tourner une fois en recette et production - return fixRDVACollections() case "control:applications": return controlApplications() case "control:appointments": @@ -250,14 +244,8 @@ export async function runJob(job: IInternalJobsCronTask | IInternalJobsSimple): return repiseGeocoordinates() case "recruiters:get-missing-address-detail": return updateAddressDetailOnRecruitersCollection() - case "import:ficheromev4": - return importFichesRomeV4() case "import:referentielrome": return importReferentielRome() - case "migration:remove-version-key-from-all-collections": // Temporaire, doit tourner en recette et production - return removeVersionKeyFromAllCollections() - case "migration:remove-delegated-from-jobs": // Temporaire, doit tourner en recette et production - return removeIsDelegatedFromJobs() case "api:user:create": { const { nom, prenom, email, organization, scope } = job.payload return createApiUser(nom, prenom, email, organization, scope) @@ -350,16 +338,9 @@ export async function runJob(job: IInternalJobsCronTask | IInternalJobsSimple): const { parallelism } = job.payload return importReferentielOpcoFromConstructys(parseInt(parallelism)) } - case "prdv:emails:resend": { - const { fromDate } = job.payload - return repriseEmailRdvs({ fromDateStr: fromDate }) - } - /////// - case "mongodb:indexes:create": - return createMongoDBIndexes() case "anonymize-individual": { const { collection, id } = job.payload - return anonymizeIndividual({ collection, id }) + return anonymizeIndividual({ collection, id: new ObjectId(id) }) } case "db:validate": return validateModels() diff --git a/server/src/jobs/jobs_actions.ts b/server/src/jobs/jobs_actions.ts index 309c6ed733..116ed78565 100644 --- a/server/src/jobs/jobs_actions.ts +++ b/server/src/jobs/jobs_actions.ts @@ -1,13 +1,12 @@ import { captureException, getCurrentHub, runWithAsyncContext } from "@sentry/node" import { formatDuration, intervalToDuration } from "date-fns" -import mongoose from "mongoose" -import { IInternalJobs, IInternalJobsSimple } from "@/common/model/schema/internalJobs/internalJobs.types" -import { db } from "@/common/mongodb" +import { IInternalJobs, IInternalJobsSimple } from "@/common/model/internalJobs.types" import { sleep } from "@/common/utils/asyncUtils" import { notifyToSlack } from "@/common/utils/slackUtils" import { getLoggerWithContext } from "../common/logger" +import { getDbCollection } from "../common/utils/mongodbUtils" import config from "../config" import { createJobSimple, updateJob } from "./job.actions" @@ -49,7 +48,7 @@ export async function processor(signal: AbortSignal): Promise { logger.debug(`Process jobs queue - looking for a job to execute`) - const { value: nextJob } = await db.collection("internalJobs").findOneAndUpdate( + const nextJob = await getDbCollection("internalJobs").findOneAndUpdate( { type: { $in: ["simple", "cron_task"] }, status: "pending", @@ -79,7 +78,7 @@ const runner = async (job: IInternalJobs, jobFunc: () => Promise): Prom jobLogger.info("job started") const startDate = new Date() - await updateJob(new mongoose.Types.ObjectId(job._id), { + await updateJob(job._id, { status: "running", started_at: startDate, }) @@ -100,7 +99,7 @@ const runner = async (job: IInternalJobs, jobFunc: () => Promise): Prom const ts = endDate.getTime() - startDate.getTime() const duration = formatDuration(intervalToDuration({ start: startDate, end: endDate })) || `${ts}ms` const status = error ? "errored" : "finished" - await updateJob(new mongoose.Types.ObjectId(job._id), { + await updateJob(job._id, { status: error ? "errored" : "finished", output: { duration, result, error }, ended_at: endDate, diff --git a/server/src/jobs/lba_recruteur/api/createApiUser.ts b/server/src/jobs/lba_recruteur/api/createApiUser.ts index 7a74e5fac4..90dcf0be79 100644 --- a/server/src/jobs/lba_recruteur/api/createApiUser.ts +++ b/server/src/jobs/lba_recruteur/api/createApiUser.ts @@ -1,7 +1,10 @@ +import { randomUUID } from "crypto" + +import { ObjectId } from "mongodb" import { ICredential } from "shared/models" import { logger } from "../../../common/logger" -import { Credential } from "../../../common/model/index" +import { getDbCollection } from "../../../common/utils/mongodbUtils" export const createApiUser = async ( nom: ICredential["nom"], @@ -10,6 +13,19 @@ export const createApiUser = async ( organisation: ICredential["organisation"], scope: ICredential["scope"] ) => { - const apiUser = await Credential.create({ nom, prenom, email, organisation, scope }) - logger.info(`API-KEY : ${apiUser.api_key}`) + const now = new Date() + const newUser: ICredential = { + _id: new ObjectId(), + nom, + prenom, + email, + organisation, + scope, + actif: true, + api_key: `mna-${randomUUID()}`, + createdAt: now, + updatedAt: now, + } + await getDbCollection("credentials").insertOne(newUser) + logger.info(`API-KEY : ${newUser.api_key}`) } diff --git a/server/src/jobs/lba_recruteur/api/disableApiUser.ts b/server/src/jobs/lba_recruteur/api/disableApiUser.ts index e5e79d1c86..ffad4ccbb4 100644 --- a/server/src/jobs/lba_recruteur/api/disableApiUser.ts +++ b/server/src/jobs/lba_recruteur/api/disableApiUser.ts @@ -1,10 +1,10 @@ import { ICredential } from "shared/models" import { logger } from "../../../common/logger" -import { Credential } from "../../../common/model/index" +import { getDbCollection } from "../../../common/utils/mongodbUtils" export const disableApiUser = async (email: ICredential["email"], state: ICredential["actif"] = false) => { - const updatedUser = await Credential.findOneAndUpdate({ email }, { actif: state }, { new: true }) + const updatedUser = await getDbCollection("credentials").findOneAndUpdate({ email }, { $set: { actif: state } }, { returnDocument: "after" }) logger.info(`User ${updatedUser?.email} disabled — API state : ${updatedUser?.actif}`) } diff --git a/server/src/jobs/lba_recruteur/api/resetApiKey.ts b/server/src/jobs/lba_recruteur/api/resetApiKey.ts index 7d5932d8f1..59082ec094 100644 --- a/server/src/jobs/lba_recruteur/api/resetApiKey.ts +++ b/server/src/jobs/lba_recruteur/api/resetApiKey.ts @@ -1,8 +1,9 @@ +import { randomUUID } from "crypto" + import { logger } from "../../../common/logger" -import { Credential } from "../../../common/model/index" -import { createApiKey } from "../../../services/userRecruteur.service" +import { getDbCollection } from "../../../common/utils/mongodbUtils" export const resetApiKey = async (email) => { - const updatedUser = await Credential.findOneAndUpdate({ email }, { api_key: createApiKey() }, { new: true }) + const updatedUser = await getDbCollection("credentials").findOneAndUpdate({ email }, { $set: { api_key: `mna-${randomUUID()}` } }, { returnDocument: "after" }) logger.info(`API-KEY : ${updatedUser?.api_key}`) } diff --git a/server/src/jobs/lba_recruteur/formulaire/annuleFormulaire.ts b/server/src/jobs/lba_recruteur/formulaire/annuleFormulaire.ts index b611c7490d..a9e0fa4fc8 100644 --- a/server/src/jobs/lba_recruteur/formulaire/annuleFormulaire.ts +++ b/server/src/jobs/lba_recruteur/formulaire/annuleFormulaire.ts @@ -1,7 +1,8 @@ import { JOB_STATUS } from "shared/models" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../common/logger" -import { Recruiter } from "../../../common/model/index" import { asyncForEach } from "../../../common/utils/asyncUtils" import { notifyToSlack } from "../../../common/utils/slackUtils" import dayjs from "../../../services/dayjs.service" @@ -9,10 +10,12 @@ import dayjs from "../../../services/dayjs.service" export const annuleFormulaire = async () => { const today = dayjs().startOf("day").utc(true) - const formulaires = await Recruiter.find({ - "jobs.job_status": JOB_STATUS.ACTIVE, - "jobs.job_expiration_date": { $lte: today }, - }).lean() + const formulaires = await getDbCollection("recruiters") + .find({ + "jobs.job_status": JOB_STATUS.ACTIVE, + "jobs.job_expiration_date": { $lte: today }, + }) + .toArray() // reduce formulaire with eligible offers const offersToCancel = formulaires.reduce((acc: any[], formulaire) => { @@ -35,7 +38,10 @@ export const annuleFormulaire = async () => { } await asyncForEach(offersToCancel, async (job) => { - await Recruiter.findOneAndUpdate({ "jobs._id": job._id }, { $set: { "jobs.$.job_status": JOB_STATUS.ANNULEE } }) + await getDbCollection("recruiters").findOneAndUpdate( + { "jobs._id": job._id }, + { $set: { "jobs.$.job_status": JOB_STATUS.ANNULEE, updatedAt: new Date(), "jobs.$.job_update_date": new Date() } } + ) }) logger.info(`${offersToCancel.length} offres expirés`) diff --git a/server/src/jobs/lba_recruteur/formulaire/fixJobExpirationDate.ts b/server/src/jobs/lba_recruteur/formulaire/fixJobExpirationDate.ts index da6bf33911..5cc7b41d34 100644 --- a/server/src/jobs/lba_recruteur/formulaire/fixJobExpirationDate.ts +++ b/server/src/jobs/lba_recruteur/formulaire/fixJobExpirationDate.ts @@ -1,17 +1,19 @@ import dayjs from "dayjs" import { logger } from "@/common/logger" -import { Recruiter } from "@/common/model" import { asyncForEach } from "@/common/utils/asyncUtils" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sentryCaptureException } from "@/common/utils/sentryUtils" import { notifyToSlack } from "@/common/utils/slackUtils" import { addExpirationPeriod, updateOffre } from "@/services/formulaire.service" export const fixJobExpirationDate = async () => { const latestExpirationDate = addExpirationPeriod(dayjs()) - const recruiters = await Recruiter.find({ - "jobs.job_expiration_date": { $gt: latestExpirationDate.toDate() }, - }).lean() + const recruiters = await getDbCollection("recruiters") + .find({ + "jobs.job_expiration_date": { $gt: latestExpirationDate.toDate() }, + }) + .toArray() const stats = { success: 0, failure: 0, jobSuccess: 0 } logger.info(`Correction des dates d'expiration des offres: ${recruiters.length} recruteurs à mettre à jour...`) await asyncForEach(recruiters, async (recruiter) => { diff --git a/server/src/jobs/lba_recruteur/formulaire/fixJobType.ts b/server/src/jobs/lba_recruteur/formulaire/fixJobType.ts index 31c8c0493b..af386c776f 100644 --- a/server/src/jobs/lba_recruteur/formulaire/fixJobType.ts +++ b/server/src/jobs/lba_recruteur/formulaire/fixJobType.ts @@ -1,8 +1,8 @@ import { TRAINING_CONTRACT_TYPE } from "shared/constants/recruteur" import { logger } from "@/common/logger" -import { Recruiter } from "@/common/model" import { asyncForEach } from "@/common/utils/asyncUtils" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sentryCaptureException } from "@/common/utils/sentryUtils" import { notifyToSlack } from "@/common/utils/slackUtils" import { updateOffre } from "@/services/formulaire.service" @@ -10,9 +10,11 @@ import { updateOffre } from "@/services/formulaire.service" export const fixJobType = async () => { const misspelledProfessionalisation = "Professionalisation" - const recruiters = await Recruiter.find({ - "jobs.job_type": misspelledProfessionalisation, - }).lean() + const recruiters = await getDbCollection("recruiters") + .find({ + "jobs.job_type": misspelledProfessionalisation, + }) + .toArray() const stats = { success: 0, failure: 0 } logger.info(`Correction des job type=Professionalisation: ${recruiters.length} recruteurs à mettre à jour...`) await asyncForEach(recruiters, async (recruiter) => { diff --git a/server/src/jobs/lba_recruteur/formulaire/fixRecruiterDataValidation.ts b/server/src/jobs/lba_recruteur/formulaire/fixRecruiterDataValidation.ts index 6c765a181a..5b7cfc3ae3 100644 --- a/server/src/jobs/lba_recruteur/formulaire/fixRecruiterDataValidation.ts +++ b/server/src/jobs/lba_recruteur/formulaire/fixRecruiterDataValidation.ts @@ -3,8 +3,8 @@ import { TRAINING_RYTHM } from "shared/constants/recruteur" import { z } from "zod" import { logger } from "@/common/logger" -import { Recruiter } from "@/common/model" import { asyncForEach } from "@/common/utils/asyncUtils" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sentryCaptureException } from "@/common/utils/sentryUtils" import { notifyToSlack } from "@/common/utils/slackUtils" import { updateOffre } from "@/services/formulaire.service" @@ -12,9 +12,11 @@ import { getRomeDetailsFromDB } from "@/services/rome.service" const fixDates = async () => { const subject = "Fix data validations pour recruiters : delegations.cfa_read_company_detail_at" - const recruiters = await Recruiter.find({ - "jobs.delegations.cfa_read_company_detail_at": { $type: "string" }, - }).lean() + const recruiters = await getDbCollection("recruiters") + .find({ + "jobs.delegations.cfa_read_company_detail_at": { $type: "string" }, + }) + .toArray() const stats = { success: 0, failure: 0 } logger.info(`${subject}: ${recruiters.length} recruteurs à mettre à jour...`) await asyncForEach(recruiters, async (recruiter) => { @@ -50,13 +52,11 @@ const fixDates = async () => { const fixRomeDetails = async () => { const subject = "Fix data validations pour recruiters : rome_detail" - const recruiters = await Recruiter.find( - { + const recruiters = await getDbCollection("recruiters") + .find({ "jobs.rome_detail": { $type: "string" }, - }, - undefined, - { runValidators: false, rawResult: true } - ).lean() + }) + .toArray() const stats = { success: 0, failure: 0 } logger.info(`${subject}: ${recruiters.length} recruteurs à mettre à jour...`) await asyncForEach(recruiters, async (recruiter) => { @@ -91,16 +91,18 @@ const fixRomeDetails = async () => { const fixJobRythm = async () => { const subject = "Fix data validations : job_rythm" - const recruiters = await Recruiter.find({ - $or: [ - { - "jobs.job_rythm": "1 jours / 4 jours", - }, - { - "jobs.job_rythm": "", - }, - ], - }).lean() + const recruiters = await getDbCollection("recruiters") + .find({ + $or: [ + { + "jobs.job_rythm": "1 jours / 4 jours", + }, + { + "jobs.job_rythm": "", + }, + ], + }) + .toArray() const stats = { success: 0, failure: 0 } logger.info(`${subject}: ${recruiters.length} recruteurs à mettre à jour...`) await asyncForEach(recruiters, async (recruiter) => { diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/getOpcofromSiret.ts b/server/src/jobs/lba_recruteur/formulaire/misc/getOpcofromSiret.ts index dc93219497..98d8eae8de 100644 --- a/server/src/jobs/lba_recruteur/formulaire/misc/getOpcofromSiret.ts +++ b/server/src/jobs/lba_recruteur/formulaire/misc/getOpcofromSiret.ts @@ -1,14 +1,17 @@ import axios from "axios" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../../common/logger" -import { Recruiter } from "../../../../common/model/index" import { asyncForEach } from "../../../../common/utils/asyncUtils" import { runScript } from "../../../scriptWrapper" const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) runScript(async () => { - const form = await Recruiter.find({ $or: [{ opco: { $exists: false } }, { opco: null }] }) + const form = await getDbCollection("recruiters") + .find({ $or: [{ opco: { $exists: false } }, { opco: null }] }) + .toArray() logger.info(`${form.length} entreprise à rechercher`) let count = 0 @@ -29,7 +32,7 @@ runScript(async () => { f.opco = data.opcoName f.idcc = data.idcc - await f.save() + await getDbCollection("recruiters").updateOne({ _id: f._id }, { $set: { ...f } }) count++ await delay(2000) }) diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/removeIsDelegatedFromJobs.ts b/server/src/jobs/lba_recruteur/formulaire/misc/removeIsDelegatedFromJobs.ts deleted file mode 100644 index e96a67a518..0000000000 --- a/server/src/jobs/lba_recruteur/formulaire/misc/removeIsDelegatedFromJobs.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { mongooseInstance } from "../../../../common/mongodb" - -export const removeIsDelegatedFromJobs = async () => { - const db = mongooseInstance.connection - - // @ts-ignore - await db.collection("recruiters").updateMany( - { "jobs.is_delegated": { $exists: true } }, - { - $unset: { "jobs.$[].is_delegated": "" }, - } - ) -} diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/repriseGeocoordinates.ts b/server/src/jobs/lba_recruteur/formulaire/misc/repriseGeocoordinates.ts index 2f1ba057fe..12552454df 100644 --- a/server/src/jobs/lba_recruteur/formulaire/misc/repriseGeocoordinates.ts +++ b/server/src/jobs/lba_recruteur/formulaire/misc/repriseGeocoordinates.ts @@ -1,9 +1,10 @@ -import { Recruiter } from "../../../../common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { asyncForEach } from "../../../../common/utils/asyncUtils" import { getGeoCoordinates } from "../../../../services/etablissement.service" export const repiseGeocoordinates = async () => { - const forms = await Recruiter.find({ geo_coordinates: "NOT FOUND" }) + const forms = await getDbCollection("recruiters").find({ geo_coordinates: "NOT FOUND" }).toArray() await asyncForEach(forms, async (form: any) => { const numeroEtRue = form.address_detail.acheminement_postal.l4 diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/sendDelegationEmailWithSecuredToken.ts b/server/src/jobs/lba_recruteur/formulaire/misc/sendDelegationEmailWithSecuredToken.ts deleted file mode 100644 index 4e2600fd0f..0000000000 --- a/server/src/jobs/lba_recruteur/formulaire/misc/sendDelegationEmailWithSecuredToken.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * One time job due to route securizetion to resend delegation email with access token - */ - -import { IJob, IRecruiter } from "shared" -import dayjs from "shared/helpers/dayjs" - -import { UnsubscribeOF } from "../../../../common/model" -import { db } from "../../../../common/mongodb" -import { getStaticFilePath } from "../../../../common/utils/getStaticFilePath" -import config from "../../../../config" -import { createCfaUnsubscribeToken, createViewDelegationLink } from "../../../../services/appLinks.service" -import mailer from "../../../../services/mailer.service" - -/** - * @description Sends the mail informing the CFA that a company wants the CFA to handle the offer. - */ -export async function sendDelegationMailToCFAERRATUM(email: string, offre: IJob, recruiter: IRecruiter, siret_code: string) { - const unsubscribeOF = await UnsubscribeOF.findOne({ establishment_siret: siret_code }) - if (unsubscribeOF) return - const unsubscribeToken = createCfaUnsubscribeToken(email, siret_code) - await mailer.sendEmail({ - to: email, - subject: `[ERRATUM-2] Une entreprise recrute dans votre domaine`, - template: getStaticFilePath("./templates/mail-cfa-delegation-erratum.mjml.ejs"), - data: { - images: { - logoLba: `${config.publicUrl}/images/emails/logo_LBA.png?raw=true`, - }, - enterpriseName: recruiter.establishment_raison_sociale, - jobName: offre.rome_appellation_label, - contractType: (offre.job_type ?? []).join(", "), - trainingLevel: offre.job_level_label, - startDate: dayjs(offre.job_start_date).format("DD/MM/YYYY"), - duration: offre.job_duration, - rhythm: offre.job_rythm, - offerButton: createViewDelegationLink(email, recruiter.establishment_id, offre._id.toString(), siret_code), - createAccountButton: `${config.publicUrl}/espace-pro/creation/cfa`, - unsubscribeUrl: `${config.publicUrl}/espace-pro/proposition/formulaire/${recruiter.establishment_id}/offre/${offre._id}/siret/${siret_code}/unsubscribe?token=${unsubscribeToken}`, - }, - }) -} - -export const resendDelegationEmailWithAccessToken = async () => { - const startDate = dayjs("2023-11-01").toDate() - const endDate = dayjs("2023-11-30").toDate() - const recruiters: AsyncIterable = await db - .collection("recruiters") - .find({ createdAt: { $gte: startDate, $lt: endDate }, $nor: [{ jobs: { $exists: false } }, { jobs: { $size: 0 } }] }) - .toArray() - for await (const recruiter of recruiters) { - const { jobs }: { jobs: IJob[] } = recruiter - for await (const job of jobs) { - if (!job.delegations?.length) { - break - } - for await (const delegation of job.delegations) { - const { email, siret_code } = delegation - await sendDelegationMailToCFAERRATUM(email, job, recruiter, siret_code) - } - } - } -} diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/updateAddressDetailOnRecruitersCollection.ts b/server/src/jobs/lba_recruteur/formulaire/misc/updateAddressDetailOnRecruitersCollection.ts index 543108e8b5..ed2cb2201c 100644 --- a/server/src/jobs/lba_recruteur/formulaire/misc/updateAddressDetailOnRecruitersCollection.ts +++ b/server/src/jobs/lba_recruteur/formulaire/misc/updateAddressDetailOnRecruitersCollection.ts @@ -1,11 +1,12 @@ +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../../common/logger" -import { Recruiter } from "../../../../common/model/index" import { asyncForEach, delay } from "../../../../common/utils/asyncUtils" import { getEtablissementFromGouv } from "../../../../services/etablissement.service" export const updateAddressDetailOnRecruitersCollection = async () => { logger.info("Start update user adresse detail") - const etablissements = await Recruiter.find({ address_detail: null }) + const etablissements = await getDbCollection("recruiters").find({ address_detail: null }).toArray() logger.info(`${etablissements.length} entries to update...`) @@ -21,7 +22,7 @@ export const updateAddressDetailOnRecruitersCollection = async () => { etb.address_detail = etablissement?.data.adresse - await etb.save() + await getDbCollection("recruiters").updateOne({ _id: etb._id }, { $set: { ...etb } }) } catch (error: any) { const { errors } = error.response.data @@ -30,8 +31,8 @@ export const updateAddressDetailOnRecruitersCollection = async () => { errors.includes("Le numéro de siret n'est pas correctement formatté") || errors.includes("Le siret ou siren indiqué n'existe pas, n'est pas connu ou ne comporte aucune information pour cet appel") ) { - console.warn(`Invalid siret DELETED : ${etb.establishment_siret}`) - await Recruiter.findByIdAndDelete(etb._id) + console.log(`Invalid siret DELETED : ${etb.establishment_siret}`) + await getDbCollection("recruiters").deleteOne({ _id: etb._id }) return } } else { diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingDelegationCount.ts b/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingDelegationCount.ts index af59d07ef0..098755e502 100644 --- a/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingDelegationCount.ts +++ b/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingDelegationCount.ts @@ -1,13 +1,16 @@ import { IJob } from "shared" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../../common/logger" -import { Recruiter } from "../../../../common/model/index" import { asyncForEach } from "../../../../common/utils/asyncUtils" import { runScript } from "../../../scriptWrapper" runScript(async () => { logger.info("Start update delegation count job") - const forms = await Recruiter.find({ "jobs.delegations": { $not: { $size: 0 }, $ne: null }, jobs: { $not: { $size: 0 } } }) + const forms = await getDbCollection("recruiters") + .find({ "jobs.delegations": { $not: { $size: 0 }, $ne: null }, jobs: { $not: { $size: 0 } } }) + .toArray() await asyncForEach(forms, async (form) => { await asyncForEach(form.jobs, async (job: IJob) => { @@ -15,7 +18,7 @@ runScript(async () => { job.job_delegation_count = job.delegations.length } }) - await form.save({ timestamps: false }) + await getDbCollection("recruiters").updateOne({ _id: form._id }, { $set: { ...form } }) }) logger.info("End update delegation count job") }) diff --git a/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingStartDate.ts b/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingStartDate.ts index 38662e1d74..08c7929312 100644 --- a/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingStartDate.ts +++ b/server/src/jobs/lba_recruteur/formulaire/misc/updateMissingStartDate.ts @@ -1,10 +1,11 @@ +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../../common/logger" -import { Recruiter } from "../../../../common/model/index" import { asyncForEach } from "../../../../common/utils/asyncUtils" export const updateMissingStartDate = async () => { logger.info("Start update missing job_start_date") - const forms = await Recruiter.find({ "jobs.job_start_date": null }) + const forms = await getDbCollection("recruiters").find({ "jobs.job_start_date": null }).toArray() await asyncForEach(forms, async (form) => { await asyncForEach(form.jobs, async (job) => { if (job.job_start_date === null) { @@ -13,7 +14,7 @@ export const updateMissingStartDate = async () => { } } }) - await form.save({ timestamps: false }) + await getDbCollection("recruiters").updateOne({ _id: form._id }, { $set: { ...form } }) }) logger.info("End update missing job_start_date") } diff --git a/server/src/jobs/lba_recruteur/formulaire/relanceFormulaire.ts b/server/src/jobs/lba_recruteur/formulaire/relanceFormulaire.ts index 755c457864..2f5d8cd57b 100644 --- a/server/src/jobs/lba_recruteur/formulaire/relanceFormulaire.ts +++ b/server/src/jobs/lba_recruteur/formulaire/relanceFormulaire.ts @@ -1,13 +1,14 @@ import Boom from "boom" import { groupBy } from "lodash-es" +import { ObjectId } from "mongodb" import { JOB_STATUS } from "shared/models" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sentryCaptureException } from "@/common/utils/sentryUtils" import { userWithAccountToUserForToken } from "@/security/accessTokenService" import { logger } from "../../../common/logger" -import { Recruiter, UserWithAccount } from "../../../common/model/index" import { asyncForEach } from "../../../common/utils/asyncUtils" import { notifyToSlack } from "../../../common/utils/slackUtils" import config from "../../../config" @@ -16,10 +17,12 @@ import dayjs from "../../../services/dayjs.service" import mailer, { sanitizeForEmail } from "../../../services/mailer.service" export const relanceFormulaire = async (threshold: number /* number of days to expiration for the reminder email to be sent */) => { - const recruiters = await Recruiter.find({ - $nor: [{ jobs: { $exists: false } }, { jobs: { $size: 0 } }], - "jobs.job_status": JOB_STATUS.ACTIVE, - }).lean() + const recruiters = await getDbCollection("recruiters") + .find({ + $nor: [{ jobs: { $exists: false } }, { jobs: { $size: 0 } }], + "jobs.job_status": JOB_STATUS.ACTIVE, + }) + .toArray() const jobsWithRecruteurs = recruiters.flatMap((recruiter) => { return recruiter.jobs.flatMap((job) => { @@ -54,7 +57,7 @@ export const relanceFormulaire = async (threshold: number /* number of days to e if (!managed_by) { throw Boom.internal(`inattendu : managed_by manquant pour le formulaire id=${recruiter._id}`) } - const contactUser = await UserWithAccount.findOne({ _id: managed_by }).lean() + const contactUser = await getDbCollection("userswithaccounts").findOne({ _id: new ObjectId(managed_by) }) if (!contactUser) { throw Boom.internal(`inattendu : impossible de trouver l'utilisateur gérant le formulaire id=${recruiter._id}`) } diff --git a/server/src/jobs/lba_recruteur/opco/constructys/constructysImporter.ts b/server/src/jobs/lba_recruteur/opco/constructys/constructysImporter.ts index c632cb654a..f8fdbc10a6 100644 --- a/server/src/jobs/lba_recruteur/opco/constructys/constructysImporter.ts +++ b/server/src/jobs/lba_recruteur/opco/constructys/constructysImporter.ts @@ -5,18 +5,18 @@ import { oleoduc, transformData, writeData } from "oleoduc" import { removeAccents } from "shared" import { OPCOS } from "shared/constants/recruteur" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { notifyToSlack } from "@/common/utils/slackUtils" import { prepareReferentielOpcoForInsert } from "@/services/opco.service" import __dirname from "../../../../common/dirname" import { logger } from "../../../../common/logger" -import { ReferentielOpco } from "../../../../common/model/index" import { fileDownloader, parseCsv } from "../../../../common/utils/fileUtils" import config from "../../../../config" const importer = async (filePath: string, opco_label: OPCOS, parallelism: number) => { logger.info(`Deleting collection entries for ${opco_label}...`) - await ReferentielOpco.deleteMany({ opco_label }) + await getDbCollection("referentielopcos").deleteMany({ opco_label }) logger.info("Importing Data...") @@ -49,7 +49,7 @@ const importer = async (filePath: string, opco_label: OPCOS, parallelism: number writeData( async (referentiel) => { const { siret_code } = referentiel - await ReferentielOpco.findOneAndUpdate({ siret_code }, { $set: referentiel }, { upsert: true }).lean() + await getDbCollection("referentielopcos").findOneAndUpdate({ siret_code }, { $set: referentiel }, { upsert: true }) }, { parallel: parallelism } ) diff --git a/server/src/jobs/lba_recruteur/opco/misc/correctAktoName.ts b/server/src/jobs/lba_recruteur/opco/misc/correctAktoName.ts deleted file mode 100644 index 2f31c42489..0000000000 --- a/server/src/jobs/lba_recruteur/opco/misc/correctAktoName.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { db } from "@/common/mongodb" - -import { runScript } from "../../../scriptWrapper" - -runScript(async () => { - await db.collection("opcos").updateMany({ opco: "akto" }, [{ $set: { opco: "AKTO / Opco entreprises et salariés des services à forte intensité de main d'oeuvre" } }]) -}) diff --git a/server/src/jobs/lba_recruteur/opco/ocapiat/ocapiatImporter.ts b/server/src/jobs/lba_recruteur/opco/ocapiat/ocapiatImporter.ts index 1e97b4fe70..b7abf465c3 100644 --- a/server/src/jobs/lba_recruteur/opco/ocapiat/ocapiatImporter.ts +++ b/server/src/jobs/lba_recruteur/opco/ocapiat/ocapiatImporter.ts @@ -2,11 +2,13 @@ import { createReadStream } from "fs" import path from "path" import Joi from "joi" +import { ObjectId } from "mongodb" import { filterData, oleoduc, transformData, writeData } from "oleoduc" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import __dirname from "../../../../common/dirname" import { logger } from "../../../../common/logger" -import { ReferentielOpco } from "../../../../common/model/index" import { fileDownloader, parseCsv } from "../../../../common/utils/fileUtils" import config from "../../../../config" import { runScript } from "../../../scriptWrapper" @@ -16,7 +18,7 @@ const importer = async (filePath, remoteFileName, opco_label) => { await fileDownloader(filePath, remoteFileName, config.ftp.ocapiat) logger.info(`Deleting collection entries for ${opco_label}...`) - await ReferentielOpco.deleteMany({ opco_label }) + await getDbCollection("referentielopcos").deleteMany({ opco_label }) logger.info("Importing Data...") @@ -54,7 +56,7 @@ const importer = async (filePath, remoteFileName, opco_label) => { }), writeData( async ({ siret_code, emails }) => { - await ReferentielOpco.create({ opco_label, siret_code, emails }) + await getDbCollection("referentielopcos").insertOne({ _id: new ObjectId(), opco_label, siret_code, emails }) }, { parallel: 500 } ) diff --git a/server/src/jobs/lba_recruteur/opco/relanceOpco.ts b/server/src/jobs/lba_recruteur/opco/relanceOpco.ts index 1a58cabfbf..b77de1c9b0 100644 --- a/server/src/jobs/lba_recruteur/opco/relanceOpco.ts +++ b/server/src/jobs/lba_recruteur/opco/relanceOpco.ts @@ -1,10 +1,11 @@ +import { ObjectId } from "mongodb" import { isEnum } from "shared" import { OPCOS } from "shared/constants/recruteur" import { AccessEntityType, AccessStatus } from "shared/models/roleManagement.model" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" -import { Entreprise, RoleManagement, UserWithAccount } from "../../../common/model/index" import { asyncForEach } from "../../../common/utils/asyncUtils" import config from "../../../config" import mailer from "../../../services/mailer.service" @@ -14,18 +15,26 @@ import mailer from "../../../services/mailer.service" * @returns {} */ export const relanceOpco = async () => { - const rolesAwaitingValidation = await RoleManagement.find( - { - $expr: { $eq: [{ $arrayElemAt: ["$status.status", -1] }, AccessStatus.AWAITING_VALIDATION] }, - authorized_type: AccessEntityType.ENTREPRISE, - }, - { authorized_id: 1 } - ).lean() + const rolesAwaitingValidation = await getDbCollection("rolemanagements") + .find( + { + $expr: { $eq: [{ $arrayElemAt: ["$status.status", -1] }, AccessStatus.AWAITING_VALIDATION] }, + authorized_type: AccessEntityType.ENTREPRISE, + }, + { + projection: { + authorized_id: 1, + }, + } + ) + .toArray() // Cancel the job if there's no users awaiting validation if (!rolesAwaitingValidation.length) return - const entreprises = await Entreprise.find({ _id: { $in: rolesAwaitingValidation.map(({ authorized_id }) => authorized_id) } }) + const entreprises = await getDbCollection("entreprises") + .find({ _id: { $in: rolesAwaitingValidation.map(({ authorized_id }) => new ObjectId(authorized_id.toString())) } }) + .toArray() const opcoCounts = entreprises.reduce>( (acc, entreprise) => { const { opco } = entreprise @@ -41,8 +50,10 @@ export const relanceOpco = async () => { await Promise.all( Object.entries(opcoCounts).map(async ([opco, count]) => { // Get related user to send the email - const roles = await RoleManagement.find({ authorized_type: AccessEntityType.OPCO, authorized_id: opco }).lean() - const users = await UserWithAccount.find({ _id: { $in: roles.map((role) => role.user_id) } }) + const roles = await getDbCollection("rolemanagements").find({ authorized_type: AccessEntityType.OPCO, authorized_id: opco }).toArray() + const users = await getDbCollection("userswithaccounts") + .find({ _id: { $in: roles.map((role) => role.user_id) } }) + .toArray() await asyncForEach(users, async (user) => { await mailer.sendEmail({ diff --git a/server/src/jobs/lba_recruteur/optout/getAllEtablissements.ts b/server/src/jobs/lba_recruteur/optout/getAllEtablissements.ts index 6fd04dedda..e18a8ca24c 100644 --- a/server/src/jobs/lba_recruteur/optout/getAllEtablissements.ts +++ b/server/src/jobs/lba_recruteur/optout/getAllEtablissements.ts @@ -1,7 +1,9 @@ +// import { ObjectId } from "mongodb" import axios from "axios" import { differenceBy } from "lodash-es" -import { Optout } from "../../../common/model/index" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { formatReferentielData } from "../../../services/etablissement.service" import { runScript } from "../../scriptWrapper" @@ -31,7 +33,7 @@ const getEtablissements = async (options?: { page: number }): Promise { const referentiel = await getEtablissements() - const data = await Optout.find({}).lean() + const data = await getDbCollection("optouts").find({}).toArray() const newEtablissement = differenceBy(referentiel, data, "siret") const organismes = newEtablissement.filter((etablissement) => etablissement.contacts.length > 0 && etablissement.adresse) @@ -66,13 +68,15 @@ runScript(async () => { await Promise.all( organismesFiltered.map(async (x) => { - // TODO wtf is this ? + // TODO à revoir, formated ne correspond pas du tout au modèle Optout const formated = formatReferentielData(x) - await Optout.create(formated) + console.log(formated) + //TODO fix and restore : + //await getDbCollection("optouts").insertOne({ _id: new ObjectId(), createdAt: new Date(), updatedAt: new Date(), ...formated }) }) ) - const count = await Optout.countDocuments() + const count = await getDbCollection("optouts").countDocuments() return { total: referentiel.length, diff --git a/server/src/jobs/lba_recruteur/seed/createOffre.ts b/server/src/jobs/lba_recruteur/seed/createOffre.ts index 3338825d4d..054452b700 100644 --- a/server/src/jobs/lba_recruteur/seed/createOffre.ts +++ b/server/src/jobs/lba_recruteur/seed/createOffre.ts @@ -1,74 +1,72 @@ +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../common/logger" -import { Recruiter, Job } from "../../../common/model/index" export const createOffreCollection = async () => { logger.info("Creating offres collections...") - await Recruiter.aggregate([ - { $unwind: "$jobs" }, - { - $project: { - // champs générés ou supprimés - jobId: "$jobs._id", - recruiterId: "$_id", - recruiterStatus: "$status", - _id: 0, + await getDbCollection("recruiters") + .aggregate([ + { $unwind: "$jobs" }, + { + $project: { + // champs générés ou supprimés + jobId: { $toString: "$jobs._id" }, + recruiterId: "$_id", + recruiterStatus: "$status", + _id: 0, - // champs de recruiters.jobs - rome_label: "$jobs.rome_label", - rome_appellation_label: "$jobs.rome_appellation_label", - job_level_label: "$jobs.job_level_label", - job_start_date: "$jobs.job_start_date", - job_description: "$jobs.job_description", - job_employer_description: "$jobs.job_employer_description", - rome_code: "$jobs.rome_code", - job_creation_date: "$jobs.job_creation_date", - job_expiration_date: "$jobs.job_expiration_date", - job_update_date: "$jobs.job_update_date", - job_last_prolongation_date: "$jobs.job_last_prolongation_date", - job_prolongation_count: "$jobs.job_prolongation_count", - relance_mail_sent: "$jobs.relance_mail_sent", - job_status: "$jobs.job_status", - job_status_comment: "$jobs.job_status_comment", - job_type: "$jobs.job_type", - is_multi_published: "$jobs.is_multi_published", - job_delegation_count: "$jobs.job_delegation_count", - delegations: "$jobs.delegations", - is_disabled_elligible: "$jobs.is_disabled_elligible", - job_count: "$jobs.job_count", - job_duration: "$jobs.job_duration", - job_rythm: "$jobs.job_rythm", - custom_address: "$jobs.custom_address", - custom_geo_coordinates: "$jobs.custom_geo_coordinates", - stats_detail_view: "$jobs.stats_detail_view", - stats_search_view: "$jobs.stats_search_view", + // champs de recruiters.jobs + rome_label: "$jobs.rome_label", + rome_appellation_label: "$jobs.rome_appellation_label", + job_level_label: "$jobs.job_level_label", + job_start_date: "$jobs.job_start_date", + job_description: "$jobs.job_description", + job_employer_description: "$jobs.job_employer_description", + rome_code: "$jobs.rome_code", + job_creation_date: "$jobs.job_creation_date", + job_expiration_date: "$jobs.job_expiration_date", + job_update_date: "$jobs.job_update_date", + job_last_prolongation_date: "$jobs.job_last_prolongation_date", + job_prolongation_count: "$jobs.job_prolongation_count", + relance_mail_sent: "$jobs.relance_mail_sent", + job_status: "$jobs.job_status", + job_status_comment: "$jobs.job_status_comment", + job_type: "$jobs.job_type", + is_multi_published: "$jobs.is_multi_published", + job_delegation_count: "$jobs.job_delegation_count", + delegations: "$jobs.delegations", + is_disabled_elligible: "$jobs.is_disabled_elligible", + job_count: "$jobs.job_count", + job_duration: "$jobs.job_duration", + job_rythm: "$jobs.job_rythm", + custom_address: "$jobs.custom_address", + custom_geo_coordinates: "$jobs.custom_geo_coordinates", + stats_detail_view: "$jobs.stats_detail_view", + stats_search_view: "$jobs.stats_search_view", - // champs de recruiters - establishment_raison_sociale: 1, - establishment_id: 1, - establishment_enseigne: 1, - establishment_siret: 1, - address_detail: 1, - address: 1, - geo_coordinates: 1, - is_delegated: 1, - cfa_delegated_siret: 1, - last_name: 1, - first_name: 1, - phone: 1, - email: 1, - origin: 1, - opco: 1, - idcc: 1, - naf_code: 1, - naf_label: 1, - establishment_size: 1, - establishment_creation_date: 1, + // champs de recruiters + establishment_raison_sociale: 1, + establishment_id: 1, + establishment_enseigne: 1, + establishment_siret: 1, + address: 1, + geo_coordinates: 1, + is_delegated: 1, + cfa_delegated_siret: 1, + last_name: 1, + first_name: 1, + phone: 1, + email: 1, + origin: 1, + opco: 1, + idcc: 1, + naf_code: 1, + naf_label: 1, + establishment_size: 1, + establishment_creation_date: 1, + }, }, - }, - { $out: "jobs" }, - ]) - - const jobs = await Job.countDocuments() - - return { jobs } + { $out: "jobs" }, + ]) + .toArray() } diff --git a/server/src/jobs/lba_recruteur/user/misc/updateSiretInfosInError.ts b/server/src/jobs/lba_recruteur/user/misc/updateSiretInfosInError.ts index 1403e54b99..4e684030bc 100644 --- a/server/src/jobs/lba_recruteur/user/misc/updateSiretInfosInError.ts +++ b/server/src/jobs/lba_recruteur/user/misc/updateSiretInfosInError.ts @@ -1,11 +1,12 @@ import Boom from "boom" +import { ObjectId } from "mongodb" import { JOB_STATUS } from "shared" import { CFA, RECRUITER_STATUS } from "shared/constants/recruteur" import { EntrepriseStatus } from "shared/models/entreprise.model" import { AccessEntityType, AccessStatus } from "shared/models/roleManagement.model" import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" -import { Cfa, Entreprise, Recruiter, RoleManagement, UserWithAccount } from "@/common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { upsertEntrepriseData } from "@/services/organization.service" import { setEntrepriseInError } from "@/services/userRecruteur.service" @@ -18,9 +19,11 @@ import { EntrepriseData, getEntrepriseDataFromSiret } from "../../../../services import { archiveFormulaire, sendMailNouvelleOffre, updateFormulaire } from "../../../../services/formulaire.service" const updateEntreprisesInfosInError = async () => { - const entreprises = await Entreprise.find({ - $expr: { $in: [{ $arrayElemAt: ["$status.status", -1] }, [EntrepriseStatus.ERROR, EntrepriseStatus.A_METTRE_A_JOUR]] }, - }).lean() + const entreprises = await getDbCollection("entreprises") + .find({ + $expr: { $in: [{ $arrayElemAt: ["$status.status", -1] }, [EntrepriseStatus.ERROR, EntrepriseStatus.A_METTRE_A_JOUR]] }, + }) + .toArray() const stats = { success: 0, failure: 0, deactivated: 0 } logger.info(`Correction des entreprises en erreur: ${entreprises.length} entreprises à mettre à jour...`) await asyncForEach(entreprises, async (entreprise) => { @@ -51,9 +54,11 @@ const updateEntreprisesInfosInError = async () => { return stats } const updateRecruteursSiretInfosInError = async () => { - const recruteurs = await Recruiter.find({ - status: RECRUITER_STATUS.EN_ATTENTE_VALIDATION, - }).lean() + const recruteurs = await getDbCollection("recruiters") + .find({ + status: RECRUITER_STATUS.EN_ATTENTE_VALIDATION, + }) + .toArray() const stats = { success: 0, failure: 0, deactivated: 0 } logger.info(`Correction des recruteurs en erreur: ${recruteurs.length} user recruteurs à mettre à jour...`) await asyncForEach(recruteurs, async (recruteur) => { @@ -76,15 +81,15 @@ const updateRecruteursSiretInfosInError = async () => { if (!managed_by) { throw Boom.internal(`inattendu : managed_by vide`) } - const managingUser = await UserWithAccount.findOne({ _id: managed_by.toString() }) + const managingUser = await getDbCollection("userswithaccounts").findOne({ _id: new ObjectId(managed_by) }) if (!managingUser) { throw Boom.internal(`inattendu : managingUser non trouvé pour _id=${managed_by}`) } - const cfa = await Cfa.findOne({ siret: cfa_delegated_siret }).lean() + const cfa = await getDbCollection("cfas").findOne({ siret: cfa_delegated_siret }) if (!cfa) { throw Boom.internal(`could not find cfa with siret=${cfa_delegated_siret}`) } - const role = await RoleManagement.findOne({ user_id: managingUser._id, authorized_type: AccessEntityType.CFA, authorized_id: cfa._id.toString() }).lean() + const role = await getDbCollection("rolemanagements").findOne({ user_id: managingUser._id, authorized_type: AccessEntityType.CFA, authorized_id: cfa._id.toString() }) if (!role) { throw Boom.internal(`could not find role with user_id=${managingUser._id} and authorized_id=${cfa._id}`) } diff --git a/server/src/jobs/lbb/lbaCompaniesUtils.ts b/server/src/jobs/lbb/lbaCompaniesUtils.ts index 24d38122a3..4d9bd856aa 100644 --- a/server/src/jobs/lbb/lbaCompaniesUtils.ts +++ b/server/src/jobs/lbb/lbaCompaniesUtils.ts @@ -1,15 +1,17 @@ import fs from "fs" import path from "path" +import { ObjectId } from "mongodb" import { compose, oleoduc, writeData } from "oleoduc" -import { ILbaCompany /*, ZGeoLocation*/ } from "shared/models" +import { ILbaCompany } from "shared/models" + +import { convertStringCoordinatesToGeoPoint } from "@/common/utils/geolib" +import { getDbCollection } from "@/common/utils/mongodbUtils" import __dirname from "../../common/dirname" import { logger } from "../../common/logger" -import { EmailBlacklist, GeoLocation, Opco, LbaCompany } from "../../common/model/index" import { getFileFromS3Bucket, getS3FileLastUpdate, uploadFileToS3 } from "../../common/utils/awsUtils" // import geoData from "../../common/utils/geoData" -import { convertStringCoordinatesToGeoPoint } from "../../common/utils/geolib" import { notifyToSlack } from "../../common/utils/slackUtils" import { streamJsonArray } from "../../common/utils/streamUtils" import config from "../../config" @@ -44,7 +46,8 @@ export const removePredictionFile = async () => { */ export const checkIfAlgoFileIsNew = async (reason: string) => { const algoFileLastModificationDate = await getS3FileLastUpdate({ key: s3File }) - const currentDbCreatedDate = ((await LbaCompany.findOne({}).select({ created_at: 1, _id: 0 })) as ILbaCompany).created_at + // projection to be added, not working when migrated to mongoDB + const currentDbCreatedDate = ((await getDbCollection("bonnesboites").findOne({})) as ILbaCompany).created_at if (algoFileLastModificationDate.getTime() < currentDbCreatedDate.getTime()) { await notifyToSlack({ @@ -114,7 +117,7 @@ export const countCompaniesInFile = async (): Promise => { Initialize bonneBoite from data, add missing data from maps, */ export const getCompanyMissingData = async (rawCompany): Promise => { - const company = new LbaCompany(rawCompany) + const company = { _id: new ObjectId(), ...rawCompany } const geo = await getGeoLocationForCompany(company) if (!geo) { return null @@ -155,14 +158,14 @@ export const getCompanyMissingData = async (rawCompany): Promise { - return (await EmailBlacklist.findOne({ email })) ? null : email + return (await getDbCollection("emailblacklists").findOne({ email })) ? null : email } const getGeoLocationForCompany = async (company) => { const geoKey = `${company.street_number} ${company.street_name} ${company.zip_code}`.trim().toUpperCase() // a t on déjà une geoloc pour cette adresse - const result = await GeoLocation.findOne({ address: geoKey }) + const result = await getDbCollection("geolocations").findOne({ address: geoKey }) // si pas de geoloc on en recherche une avec la ban // if (!result) { @@ -194,7 +197,7 @@ const getGeoLocationForCompany = async (company) => { const getOpcoForCompany = async (lbaCompany) => { const siren = lbaCompany.siret.substring(0, 9) - return await Opco.findOne({ siren }) + return await getDbCollection("opcos").findOne({ siren }) } let nafScoreMap = {} diff --git a/server/src/jobs/lbb/updateGeoLocations.ts b/server/src/jobs/lbb/updateGeoLocations.ts index 71f602d0d8..580dbf36f2 100644 --- a/server/src/jobs/lbb/updateGeoLocations.ts +++ b/server/src/jobs/lbb/updateGeoLocations.ts @@ -4,11 +4,13 @@ import path from "path" import axios from "axios" import FormData from "form-data" import fsExtra from "fs-extra" +import { ObjectId } from "mongodb" import { oleoduc, readLineByLine, transformData, writeData } from "oleoduc" -import { ZGeoLocationNew } from "shared/models" +import { ZGeoLocation } from "shared/models" + +import { getDbCollection } from "@/common/utils/mongodbUtils" import __dirname from "../../common/dirname" -import { GeoLocation } from "../../common/model/index" import { logMessage } from "../../common/utils/logMessage" import { notifyToSlack } from "../../common/utils/slackUtils" @@ -55,14 +57,13 @@ const createToGeolocateFile = (addressesToGeolocate, sourceFileCount) => { } const saveGeoData = async (geoData) => { - if (ZGeoLocationNew.safeParse(geoData).success) { - const geoLocation = new GeoLocation(geoData) - - if ((await GeoLocation.countDocuments({ address: geoLocation.address })) === 0) { + geoData._id = new ObjectId() + if (ZGeoLocation.safeParse(geoData).success) { + if ((await getDbCollection("geolocations").countDocuments({ address: geoData.address })) === 0) { try { - await geoLocation.save() + await getDbCollection("geolocations").insertOne(geoData) } catch (err) { - console.error("error saving geoloc probably from duplicate restriction: ", geoLocation.address) + console.error("error saving geoloc probably from duplicate restriction: ", geoData.address) } } } diff --git a/server/src/jobs/lbb/updateLbaCompanies.ts b/server/src/jobs/lbb/updateLbaCompanies.ts index 044f0617ef..5fbaf7abd7 100644 --- a/server/src/jobs/lbb/updateLbaCompanies.ts +++ b/server/src/jobs/lbb/updateLbaCompanies.ts @@ -1,9 +1,9 @@ import { oleoduc, transformData, writeData } from "oleoduc" import { ILbaCompany, ZLbaCompany } from "shared/models/lbaCompany.model" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { checkIsDiffusible } from "@/services/etablissement.service" -import { LbaCompany, UnsubscribedLbaCompany } from "../../common/model" import { logMessage } from "../../common/utils/logMessage" import { notifyToSlack } from "../../common/utils/slackUtils" @@ -44,7 +44,15 @@ const prepareCompany = async (rawCompany): Promise => { return null } - const unsubscribedLbaCompany = await UnsubscribedLbaCompany.findOne({ siret: rawCompany.siret }, { siret: 1, _id: 0 }) + const unsubscribedLbaCompany = await getDbCollection("unsubscribedbonnesboites").findOne( + { siret: rawCompany.siret }, + { + projection: { + siret: 1, + _id: 0, + }, + } + ) if (unsubscribedLbaCompany) { return null } @@ -61,8 +69,8 @@ const processCompanies = async () => { writeData(async (lbaCompany) => { try { if (lbaCompany) { - const parsedCompany = ZLbaCompany.parse(lbaCompany.toObject()) - await LbaCompany.collection.insertOne(new LbaCompany(parsedCompany)) + const parsedCompany = ZLbaCompany.parse(lbaCompany) + await getDbCollection("bonnesboites").insertOne(parsedCompany) } } catch (err) { logMessage("error", err) @@ -111,7 +119,7 @@ export default async function updateLbaCompanies({ if (ClearMongo) { logMessage("info", `Clearing bonnesboites db...`) - await LbaCompany.deleteMany({}) + await getDbCollection("bonnesboites").deleteMany({}) } if (UseAlgoFile) { diff --git a/server/src/jobs/lbb/updateOpcoCompanies.ts b/server/src/jobs/lbb/updateOpcoCompanies.ts index f36ff22359..d1f6f2ce16 100644 --- a/server/src/jobs/lbb/updateOpcoCompanies.ts +++ b/server/src/jobs/lbb/updateOpcoCompanies.ts @@ -1,7 +1,8 @@ import { oleoduc, writeData } from "oleoduc" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { Opco } from "../../common/model/index" import { logMessage } from "../../common/utils/logMessage" import { notifyToSlack } from "../../common/utils/slackUtils" import { CFADOCK_FILTER_LIMIT, fetchOpcosFromCFADock } from "../../services/cfadock.service" @@ -75,7 +76,7 @@ export default async function updateOpcoCompanies({ if (ClearMongo) { logMessage("info", `Clearing opcos db...`) - await Opco.deleteMany({}) + await getDbCollection("opcos").deleteMany({}) } await oleoduc( @@ -83,7 +84,7 @@ export default async function updateOpcoCompanies({ writeData(async (company) => { const siren = company.siret.toString().padStart(14, "0").substring(0, 9) - if ((await Opco.countDocuments({ siren })) === 0 && !sirenWithoutOpco.has(siren)) { + if ((await getDbCollection("opcos").countDocuments({ siren })) === 0 && !sirenWithoutOpco.has(siren)) { sirenSet.add(siren) } if (sirenSet.size > 0 && sirenSet.size % CFADOCK_FILTER_LIMIT === 0) { diff --git a/server/src/jobs/lbb/updateSAVECompanies.ts b/server/src/jobs/lbb/updateSAVECompanies.ts index bfbc2dd643..60ef8ec753 100644 --- a/server/src/jobs/lbb/updateSAVECompanies.ts +++ b/server/src/jobs/lbb/updateSAVECompanies.ts @@ -1,10 +1,11 @@ +import { ObjectId } from "mongodb" import { oleoduc, transformData, writeData } from "oleoduc" +import { IUnsubscribedLbaCompany } from "shared" -import { db } from "@/common/mongodb" import { checkIsDiffusible } from "@/services/etablissement.service" -import { LbaCompany } from "../../common/model" import { logMessage } from "../../common/utils/logMessage" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { downloadSAVEFile, getCompanyMissingData, initMaps, streamSAVECompanies } from "./lbaCompaniesUtils" @@ -25,7 +26,7 @@ export const updateSAVECompanies = async () => { ), writeData(async (company) => { try { - const lbaCompany = await LbaCompany.findOne({ siret: company.siret }) + const lbaCompany = await getDbCollection("bonnesboites").findOne({ siret: company.siret }) if (lbaCompany) { if (company.raison_sociale) { @@ -51,9 +52,9 @@ export const updateSAVECompanies = async () => { } if (lbaCompany.rome_codes?.length && (await checkIsDiffusible(lbaCompany.siret))) { - await lbaCompany.save() + await getDbCollection("bonnesboites").updateOne({ _id: lbaCompany._id }, lbaCompany) } else { - await lbaCompany.remove() + await getDbCollection("bonnesboites").deleteOne({ _id: lbaCompany._id }) } } //else company no more in collection => doing nothing @@ -88,13 +89,13 @@ export const insertSAVECompanies = async () => { return null } + // est-ce que la fonction doit retourner les dates ou sont-elles présentes dans le rawCompany ? il manque le typage de la source const company = await getCompanyMissingData(rawCompany) if (company) { try { - let lbaCompany = await LbaCompany.findOne({ siret: company.siret }) + const lbaCompany = await getDbCollection("bonnesboites").findOne({ siret: company.siret }) if (!lbaCompany) { - lbaCompany = new LbaCompany(company) - await lbaCompany.save() + await getDbCollection("bonnesboites").insertOne(company) } } catch (err) { logMessage("error", err) @@ -123,9 +124,11 @@ export const removeSAVECompanies = async () => { ), writeData(async (company) => { // Ce bloc ne sera utile qu'une seule fois. - const unsubed = await db.collection("unsubscribedbonnesboites").findOne({ siret: company.siret }) + const unsubed = await getDbCollection("unsubscribedbonnesboites").findOne({ siret: company.siret }) + const now = new Date() if (!unsubed) { - const toUnsub = { + const toUnsub: IUnsubscribedLbaCompany = { + _id: new ObjectId(), siret: company.siret, raison_sociale: "", enseigne: "Suppression via script SAVE", @@ -136,15 +139,15 @@ export const removeSAVECompanies = async () => { zip_code: "", city: "", company_size: "", - created_at: new Date(), - last_update_at: new Date(), - unsubscribe_date: new Date(), + created_at: now, + last_update_at: now, + unsubscribe_date: now, unsubscribe_reason: "Autre", } - await db.collection("unsubscribedbonnesboites").insertOne(toUnsub) + await getDbCollection("unsubscribedbonnesboites").insertOne(toUnsub) } - await db.collection("bonnesboites").deleteOne({ siret: company.siret }) + await getDbCollection("bonnesboites").deleteOne({ siret: company.siret }) }) ) diff --git a/server/src/jobs/migrations/migrations.ts b/server/src/jobs/migrations/migrations.ts index 27f8f735cb..e05ef4cc86 100644 --- a/server/src/jobs/migrations/migrations.ts +++ b/server/src/jobs/migrations/migrations.ts @@ -3,10 +3,11 @@ import path from "path" import { config as mconfig, create as mcreate, status as mstatus, up as mup } from "migrate-mongo" -import { mongooseInstance } from "@/common/mongodb" import { __dirname } from "@/common/utils/esmUtils" import config from "@/config" +import { getMongodbClient } from "../../common/utils/mongodbUtils" + const myConfig = { mongodb: { url: config.mongodb.uri, @@ -44,7 +45,8 @@ export async function up() { await status() - const client = mongooseInstance.connection.getClient() + const client = getMongodbClient() + // @ts-ignore await mup(client.db(), client) } @@ -52,7 +54,7 @@ export async function up() { export async function status(): Promise { // @ts-ignore mconfig.set(myConfig) - const client = mongooseInstance.connection.getClient() + const client = getMongodbClient() // @ts-ignore const migrationStatus = await mstatus(client.db()) diff --git a/server/src/jobs/partenaireExport/exportJobsToS3.ts b/server/src/jobs/partenaireExport/exportJobsToS3.ts index 901af07555..73e007699c 100644 --- a/server/src/jobs/partenaireExport/exportJobsToS3.ts +++ b/server/src/jobs/partenaireExport/exportJobsToS3.ts @@ -2,8 +2,8 @@ import { writeFileSync } from "fs" import { LBA_ITEM_TYPE } from "shared/constants/lbaitem" -import { db } from "../../common/mongodb" import { uploadFileToS3 } from "../../common/utils/awsUtils" +import { getDbCollection } from "../../common/utils/mongodbUtils" interface IGeneratorParams { collection: "jobs" | "bonnesboites" @@ -14,7 +14,7 @@ interface IGeneratorParams { async function generateJsonExport({ collection, query, projection, fileName }: IGeneratorParams): Promise { const filePath = new URL(`./${fileName}.json`, import.meta.url) - const data = await db.collection(collection).find(query).project(projection).toArray() + const data = await getDbCollection(collection).find(query).project(projection).toArray() writeFileSync(filePath, JSON.stringify(data, null, 4)) return filePath.pathname } diff --git a/server/src/jobs/partenaireExport/exportToFranceTravail.ts b/server/src/jobs/partenaireExport/exportToFranceTravail.ts index 2287850cfa..3f5e0270bd 100644 --- a/server/src/jobs/partenaireExport/exportToFranceTravail.ts +++ b/server/src/jobs/partenaireExport/exportToFranceTravail.ts @@ -6,13 +6,11 @@ import { oleoduc, transformData, transformIntoCSV } from "oleoduc" import { RECRUITER_STATUS } from "shared/constants/recruteur" import { JOB_STATUS } from "shared/models" -import { db } from "@/common/mongodb" - import { sendCsvToFranceTravail } from "../../common/apis/FranceTravail" import { logger } from "../../common/logger" -import { Cfa } from "../../common/model/index" import { getDepartmentByZipCode } from "../../common/territoires" import { asyncForEach } from "../../common/utils/asyncUtils" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { notifyToSlack } from "../../common/utils/slackUtils" import dayjs from "../../services/dayjs.service" @@ -176,46 +174,29 @@ export const exportToFranceTravail = async (): Promise => { const threshold = dayjs().subtract(30, "days").toDate() // Retrieve only active offers - const offres: any[] = await db - .collection("jobs") - .aggregate([ - { - $match: { - job_status: JOB_STATUS.ACTIVE, - recruiterStatus: RECRUITER_STATUS.ACTIF, - geo_coordinates: { $nin: ["NOT FOUND", null] }, - job_update_date: { $gte: threshold }, - address_detail: { $ne: null }, - is_multi_published: true, - }, - }, - { - $lookup: { - from: "referentielromes", - localField: "rome_code.0", - foreignField: "rome.code_rome", - as: "referentielrome", - }, - }, - { - $unwind: { path: "$referentielrome" }, - }, - { - $set: { rome_detail: "$referentielrome" }, - }, - { - $project: { referentielrome: 0, "rome_detail._id": 0 }, - }, - ]) + const offres: any[] = await getDbCollection("jobs") + .find({ + job_status: JOB_STATUS.ACTIVE, + recruiterStatus: RECRUITER_STATUS.ACTIF, + geo_coordinates: { $nin: ["NOT FOUND", null] }, + job_update_date: { $gte: threshold }, + address_detail: { $ne: null }, + is_multi_published: true, + }) .toArray() logger.info(`get info from ${offres.length} offers...`) await asyncForEach(offres, async (offre) => { - const cfa = offre.is_delegated ? await Cfa.findOne({ siret: offre.cfa_delegated_siret }) : null - offre.job_type.map((type) => { - const cfaFields = cfa ? { address_detail: cfa.address_detail, establishment_raison_sociale: cfa.raison_sociale } : null - buffer.push({ ...offre, type, cfa: cfaFields }) - }) + const cfa = offre.is_delegated ? await getDbCollection("cfas").findOne({ siret: offre.cfa_delegated_siret }) : null + + if (typeof offre.rome_detail !== "string" && offre.rome_detail) { + offre.job_type.map(async (type) => { + if (offre.rome_detail && typeof offre.rome_detail !== "string") { + const cfaFields = cfa ? { address_detail: cfa.address_detail, establishment_raison_sociale: cfa.raison_sociale } : null + buffer.push({ ...offre, type, cfa: cfaFields }) + } + }) + } }) logger.info("Start stream to CSV...") diff --git a/server/src/jobs/rdv/activateOptoutOnEtablissementAndUpdateReferrersOnETFA.ts b/server/src/jobs/rdv/activateOptoutOnEtablissementAndUpdateReferrersOnETFA.ts index 30befca166..a683409548 100644 --- a/server/src/jobs/rdv/activateOptoutOnEtablissementAndUpdateReferrersOnETFA.ts +++ b/server/src/jobs/rdv/activateOptoutOnEtablissementAndUpdateReferrersOnETFA.ts @@ -2,9 +2,9 @@ import * as _ from "lodash-es" import { referrers } from "shared/constants/referers" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { logger } from "../../common/logger" -import { Etablissement } from "../../common/model/index" import config from "../../config" import dayjs from "../../services/dayjs.service" import * as eligibleTrainingsForAppointmentService from "../../services/eligibleTrainingsForAppointment.service" @@ -18,14 +18,16 @@ export const activateOptoutOnEtablissementAndUpdateReferrersOnETFA = async () => logger.info("Cron #activateOptOutEtablissementFormations started.") // Opt-out etablissement to activate - const etablissementsToActivate = await Etablissement.find({ - optout_activation_scheduled_date: { - $lte: new Date(), - }, - optout_refusal_date: null, - optout_activation_date: null, - gestionnaire_email: { $ne: null }, - }) + const etablissementsToActivate = await getDbCollection("etablissements") + .find({ + optout_activation_scheduled_date: { + $lte: new Date(), + }, + optout_refusal_date: null, + optout_activation_date: null, + gestionnaire_email: { $ne: null }, + }) + .toArray() // Activate all formations, for all referrers that have a mail await Promise.all( @@ -37,14 +39,16 @@ export const activateOptoutOnEtablissementAndUpdateReferrersOnETFA = async () => lieu_formation_email: { $nin: [null, ""] }, }, { - referrers: [referrers.JEUNE_1_SOLUTION.name, referrers.LBA.name], + $set: { + referrers: [referrers.JEUNE_1_SOLUTION.name, referrers.LBA.name], + }, } ), - Etablissement.findOneAndUpdate( + getDbCollection("etablissements").findOneAndUpdate( { _id: etablissement._id, }, - { optout_activation_date: new Date() } + { $set: { optout_activation_date: new Date() } } ), ]) diff --git a/server/src/jobs/rdv/anonymizeAppointments.ts b/server/src/jobs/rdv/anonymizeAppointments.ts index 185f8214f8..8be01dc69f 100644 --- a/server/src/jobs/rdv/anonymizeAppointments.ts +++ b/server/src/jobs/rdv/anonymizeAppointments.ts @@ -1,17 +1,17 @@ import { logger } from "../../common/logger" -import { Appointment } from "../../common/model/index" +import { getDbCollection } from "../../common/utils/mongodbUtils" export const anonimizeAppointments = async () => { logger.info("job #anonimizeAppointments start") const archiveThreshold = new Date() archiveThreshold.setFullYear(archiveThreshold.getFullYear() - 1) - const result = await Appointment.updateMany( + const result = await getDbCollection("appointments").updateMany( { created_at: { $lte: archiveThreshold } }, { $set: { etablissement_id: null, - cle_ministere_educatif: null, + cle_ministere_educatif: undefined, formation_id: null, motivations: null, id_rco_formation: null, diff --git a/server/src/jobs/rdv/anonymizeUsers.ts b/server/src/jobs/rdv/anonymizeUsers.ts index 9e78365d6d..692cbd9382 100644 --- a/server/src/jobs/rdv/anonymizeUsers.ts +++ b/server/src/jobs/rdv/anonymizeUsers.ts @@ -1,8 +1,7 @@ import { logger } from "@/common/logger" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { notifyToSlack } from "@/common/utils/slackUtils" -import { User } from "../../common/model/index" - /** * Anonymize users older than 1 year. */ @@ -13,23 +12,26 @@ const anonymizeUsers = async () => { lastYear.setFullYear(lastYear.getFullYear() - 1) const matchCondition = { last_action_date: { $lte: lastYear } } - await User.aggregate([ - { - $match: matchCondition, - }, - { - $project: { - role: 1, - type: 1, - last_action_date: 1, + await getDbCollection("users") + .aggregate([ + { + $match: matchCondition, + }, + { + $project: { + role: 1, + type: 1, + last_action_date: 1, + }, + }, + { + // @ts-ignore + $merge: "anonymized_users", }, - }, - { - $merge: "anonymized_users", - }, - ]) + ]) + .toArray() - const res = await User.deleteMany(matchCondition) + const res = await getDbCollection("users").deleteMany(matchCondition) return res.deletedCount } diff --git a/server/src/jobs/rdv/eligibleTrainingsForAppointmentsHistoryWithCatalogue.ts b/server/src/jobs/rdv/eligibleTrainingsForAppointmentsHistoryWithCatalogue.ts index 7f3f37571c..daabbdcf64 100644 --- a/server/src/jobs/rdv/eligibleTrainingsForAppointmentsHistoryWithCatalogue.ts +++ b/server/src/jobs/rdv/eligibleTrainingsForAppointmentsHistoryWithCatalogue.ts @@ -1,7 +1,8 @@ import { oleoduc, writeData } from "oleoduc" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { EligibleTrainingsForAppointment, eligibleTrainingsForAppointmentHistory, FormationCatalogue } from "../../common/model/index" /** * @description Check if a training is still available for appointments again it's presence in the training catalogue @@ -10,7 +11,7 @@ import { EligibleTrainingsForAppointment, eligibleTrainingsForAppointmentHistory export const eligibleTrainingsForAppointmentsHistoryWithCatalogue = async () => { logger.info("Cron #eligibleTrainingsForAppointmentsHistoryWithCatalogue started.") - const control = await FormationCatalogue.countDocuments() + const control = await getDbCollection("formationcatalogues").countDocuments() if (control === 0) { return @@ -21,26 +22,26 @@ export const eligibleTrainingsForAppointmentsHistoryWithCatalogue = async () => NewElligibleTrainingCount: 0, } - stats.AncientElligibleTrainingCount = await EligibleTrainingsForAppointment.countDocuments() + stats.AncientElligibleTrainingCount = await getDbCollection("eligible_trainings_for_appointments").countDocuments() await oleoduc( - EligibleTrainingsForAppointment.find({}).lean().cursor(), + getDbCollection("eligible_trainings_for_appointments").find({}), writeData( async (formation) => { - const exist = await FormationCatalogue.findOne({ cle_ministere_educatif: formation.cle_ministere_educatif }) + const exist = await getDbCollection("formationcatalogues").findOne({ cle_ministere_educatif: formation.cle_ministere_educatif }) formation._id = undefined if (!exist) { - await eligibleTrainingsForAppointmentHistory.create({ ...formation, email_rdv: undefined, historization_date: new Date() }) - await EligibleTrainingsForAppointment.findOneAndRemove({ cle_ministere_educatif: formation.cle_ministere_educatif }) + await getDbCollection("eligible_trainings_for_appointments_history").insertOne({ ...formation, email_rdv: undefined, historization_date: new Date() }) + await getDbCollection("eligible_trainings_for_appointments").deleteOne({ cle_ministere_educatif: formation.cle_ministere_educatif }) } }, { parallel: 20 } ) ) - stats.NewElligibleTrainingCount = await EligibleTrainingsForAppointment.countDocuments() + stats.NewElligibleTrainingCount = await getDbCollection("eligible_trainings_for_appointments").countDocuments() logger.info("Cron #eligibleTrainingsForAppointmentsHistoryWithCatalogue done.") diff --git a/server/src/jobs/rdv/importReferentielOnisep.ts b/server/src/jobs/rdv/importReferentielOnisep.ts index 8991b36ccb..9d1a32bfd9 100644 --- a/server/src/jobs/rdv/importReferentielOnisep.ts +++ b/server/src/jobs/rdv/importReferentielOnisep.ts @@ -3,10 +3,13 @@ import { writeFile } from "node:fs/promises" import { pipeline } from "stream/promises" import axios from "axios" +import { ObjectId } from "mongodb" import { filterData, oleoduc, transformData, writeData } from "oleoduc" +import { IReferentielOnisep } from "shared/models" + +import { getDbCollection } from "@/common/utils/mongodbUtils" import { logger } from "../../common/logger" -import { ReferentielOnisep } from "../../common/model/index" import { parseCsv } from "../../common/utils/fileUtils" import { sentryCaptureException } from "../../common/utils/sentryUtils" import { notifyToSlack } from "../../common/utils/slackUtils" @@ -29,7 +32,7 @@ export const importReferentielOnisep = async () => { const stats = { csvRows: 0, minCsvRowsThreshold: 10000, - beforeImportationDatabaseRows: await ReferentielOnisep.estimatedDocumentCount({}), + beforeImportationDatabaseRows: await getDbCollection("referentieloniseps").estimatedDocumentCount({}), afterImportationDatabaseRows: 0, filePath: "./widget_mna_ideo.csv", } @@ -61,7 +64,7 @@ export const importReferentielOnisep = async () => { return } - await ReferentielOnisep.deleteMany({}) + await getDbCollection("referentieloniseps").deleteMany({}) try { await oleoduc( @@ -69,15 +72,18 @@ export const importReferentielOnisep = async () => { parseCsv(), filterData((row: TCsvRow) => row["ID action IDEO2"] && row["Clé ministère éducatif MA"]), transformData((row: TCsvRow) => { - return { + const refOnisep: IReferentielOnisep = { + _id: new ObjectId(), id_action_ideo2: row["ID action IDEO2"], cle_ministere_educatif: row["Clé ministère éducatif MA"], + created_at: new Date(), } + return refOnisep }), - writeData((transformedData) => ReferentielOnisep.create(transformedData), { parallel: 10 }) + writeData((transformedData: IReferentielOnisep) => getDbCollection("referentieloniseps").insertOne(transformedData), { parallel: 10 }) ) - stats.afterImportationDatabaseRows = await ReferentielOnisep.estimatedDocumentCount({}) + stats.afterImportationDatabaseRows = await getDbCollection("referentieloniseps").estimatedDocumentCount({}) await notifyToSlack({ subject: "IMPORT ONISEP", diff --git a/server/src/jobs/rdv/inviteEtablissementAffelnetToPremium.ts b/server/src/jobs/rdv/inviteEtablissementAffelnetToPremium.ts index 5fb61d8cdf..e7d3a3ce0f 100644 --- a/server/src/jobs/rdv/inviteEtablissementAffelnetToPremium.ts +++ b/server/src/jobs/rdv/inviteEtablissementAffelnetToPremium.ts @@ -1,8 +1,8 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { createRdvaPremiumAffelnetPageLink } from "@/services/appLinks.service" import { logger } from "../../common/logger" -import { EligibleTrainingsForAppointment, Etablissement } from "../../common/model/index" import { isValidEmail } from "../../common/utils/isValidEmail" import { notifyToSlack } from "../../common/utils/slackUtils" import config from "../../config" @@ -33,35 +33,37 @@ export const inviteEtablissementAffelnetToPremium = async () => { return } - const etablissementsToInviteToPremium: Array = await Etablissement.aggregate([ - { - $match: { - gestionnaire_email: { - $ne: null, + const etablissementsToInviteToPremium: Array = (await getDbCollection("etablissements") + .aggregate([ + { + $match: { + gestionnaire_email: { + $ne: null, + }, + premium_affelnet_invitation_date: null, }, - premium_affelnet_invitation_date: null, }, - }, - { - $group: { - _id: { - gestionnaire_siret: "$gestionnaire_siret", + { + $group: { + _id: { + gestionnaire_siret: "$gestionnaire_siret", + }, + id: { $first: "$_id" }, + optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, + gestionnaire_email: { $first: "$gestionnaire_email" }, + count: { $sum: 1 }, }, - id: { $first: "$_id" }, - optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, - gestionnaire_email: { $first: "$gestionnaire_email" }, - count: { $sum: 1 }, }, - }, - ]) + ]) + .toArray()) as Array for (const etablissement of etablissementsToInviteToPremium) { // Only send an invite if the "etablissement" have at least one available Parcoursup "formation" - const hasOneAvailableFormation = await EligibleTrainingsForAppointment.findOne({ + const hasOneAvailableFormation = await getDbCollection("eligible_trainings_for_appointments").findOne({ etablissement_gestionnaire_siret: etablissement._id.gestionnaire_siret, lieu_formation_email: { $ne: null }, affelnet_visible: true, - }).lean() + }) if (!hasOneAvailableFormation || !isValidEmail(etablissement.gestionnaire_email) || !etablissement._id.gestionnaire_siret || !etablissement.gestionnaire_email) { continue @@ -88,11 +90,13 @@ export const inviteEtablissementAffelnetToPremium = async () => { }, }) - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( { gestionnaire_siret: etablissement._id.gestionnaire_siret }, { - premium_affelnet_invitation_date: dayjs().toDate(), - to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + $set: { + premium_affelnet_invitation_date: dayjs().toDate(), + to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + }, } ) } diff --git a/server/src/jobs/rdv/inviteEtablissementAffelnetToPremiumFollowUp.ts b/server/src/jobs/rdv/inviteEtablissementAffelnetToPremiumFollowUp.ts index 14f110ebe8..07227b9c62 100644 --- a/server/src/jobs/rdv/inviteEtablissementAffelnetToPremiumFollowUp.ts +++ b/server/src/jobs/rdv/inviteEtablissementAffelnetToPremiumFollowUp.ts @@ -1,8 +1,8 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { createRdvaPremiumAffelnetPageLink } from "@/services/appLinks.service" import { logger } from "../../common/logger" -import { EligibleTrainingsForAppointment, Etablissement } from "../../common/model/index" import { isValidEmail } from "../../common/utils/isValidEmail" import { notifyToSlack } from "../../common/utils/slackUtils" import config from "../../config" @@ -29,37 +29,39 @@ export const inviteEtablissementAffelnetToPremiumFollowUp = async (bypassDate: b clause = [{ premium_affelnet_invitation_date: { $ne: null } }] } - const etablissementsToInviteToPremium: Array = await Etablissement.aggregate([ - { - $match: { - gestionnaire_email: { - $ne: null, + const etablissementsToInviteToPremium: Array = (await getDbCollection("etablissements") + .aggregate([ + { + $match: { + gestionnaire_email: { + $ne: null, + }, + premium_affelnet_activation_date: null, + premium_affelnet_refusal_date: null, + premium_affelnet_follow_up_date: null, + $and: clause, }, - premium_affelnet_activation_date: null, - premium_affelnet_refusal_date: null, - premium_affelnet_follow_up_date: null, - $and: clause, }, - }, - { - $group: { - _id: { - gestionnaire_siret: "$gestionnaire_siret", + { + $group: { + _id: { + gestionnaire_siret: "$gestionnaire_siret", + }, + id: { $first: "$_id" }, + optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, + gestionnaire_email: { $first: "$gestionnaire_email" }, + count: { $sum: 1 }, }, - id: { $first: "$_id" }, - optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, - gestionnaire_email: { $first: "$gestionnaire_email" }, - count: { $sum: 1 }, }, - }, - ]) + ]) + .toArray()) as Array for (const etablissement of etablissementsToInviteToPremium) { - const hasOneAvailableFormation = await EligibleTrainingsForAppointment.findOne({ + const hasOneAvailableFormation = await getDbCollection("eligible_trainings_for_appointments").findOne({ etablissement_gestionnaire_siret: etablissement._id.gestionnaire_siret, lieu_formation_email: { $ne: null }, affelnet_visible: true, - }).lean() + }) if (!hasOneAvailableFormation || !etablissement.gestionnaire_email || !isValidEmail(etablissement.gestionnaire_email) || !etablissement._id.gestionnaire_siret) { continue @@ -87,11 +89,13 @@ export const inviteEtablissementAffelnetToPremiumFollowUp = async (bypassDate: b }, }) - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( { gestionnaire_siret: etablissement._id.gestionnaire_siret }, { - premium_affelnet_follow_up_date: dayjs().toDate(), - to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + $set: { + premium_affelnet_follow_up_date: dayjs().toDate(), + to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + }, } ) } diff --git a/server/src/jobs/rdv/inviteEtablissementParcoursupToPremium.ts b/server/src/jobs/rdv/inviteEtablissementParcoursupToPremium.ts index 59a51a7d9e..6de88fd605 100644 --- a/server/src/jobs/rdv/inviteEtablissementParcoursupToPremium.ts +++ b/server/src/jobs/rdv/inviteEtablissementParcoursupToPremium.ts @@ -1,9 +1,9 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" import { isValidEmail } from "@/common/utils/isValidEmail" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { createRdvaPremiumParcoursupPageLink } from "@/services/appLinks.service" import { logger } from "../../common/logger" -import { EligibleTrainingsForAppointment, Etablissement } from "../../common/model/index" import { notifyToSlack } from "../../common/utils/slackUtils" import config from "../../config" import dayjs from "../../services/dayjs.service" @@ -32,28 +32,30 @@ export const inviteEtablissementParcoursupToPremium = async () => { return } - const etablissementsToInviteToPremium: Array = await Etablissement.aggregate([ - { - $match: { - gestionnaire_email: { - $ne: null, + const etablissementsToInviteToPremium: Array = (await getDbCollection("etablissements") + .aggregate([ + { + $match: { + gestionnaire_email: { + $ne: null, + }, + premium_activation_date: null, + premium_invitation_date: null, }, - premium_activation_date: null, - premium_invitation_date: null, }, - }, - { - $group: { - _id: { - gestionnaire_siret: "$gestionnaire_siret", + { + $group: { + _id: { + gestionnaire_siret: "$gestionnaire_siret", + }, + id: { $first: "$_id" }, + optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, + gestionnaire_email: { $first: "$gestionnaire_email" }, + count: { $sum: 1 }, }, - id: { $first: "$_id" }, - optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, - gestionnaire_email: { $first: "$gestionnaire_email" }, - count: { $sum: 1 }, }, - }, - ]) + ]) + .toArray()) as Array let count = 0 @@ -61,11 +63,11 @@ export const inviteEtablissementParcoursupToPremium = async () => { for (const etablissement of etablissementsToInviteToPremium) { // Only send an invite if the "etablissement" have at least one available Parcoursup "formation" - const hasOneAvailableFormation = await EligibleTrainingsForAppointment.findOne({ + const hasOneAvailableFormation = await getDbCollection("eligible_trainings_for_appointments").findOne({ etablissement_gestionnaire_siret: etablissement._id.gestionnaire_siret, lieu_formation_email: { $ne: null }, parcoursup_visible: true, - }).lean() + }) if (!hasOneAvailableFormation || !isValidEmail(etablissement.gestionnaire_email) || !etablissement._id.gestionnaire_siret || !etablissement.gestionnaire_email) { continue @@ -92,11 +94,13 @@ export const inviteEtablissementParcoursupToPremium = async () => { }, }) - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( { gestionnaire_siret: etablissement._id.gestionnaire_siret }, { - premium_invitation_date: dayjs().toDate(), - to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + $set: { + premium_invitation_date: dayjs().toDate(), + to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + }, } ) } diff --git a/server/src/jobs/rdv/inviteEtablissementParcoursupToPremiumFollowUp.ts b/server/src/jobs/rdv/inviteEtablissementParcoursupToPremiumFollowUp.ts index b440e1f5d8..6949ac292e 100644 --- a/server/src/jobs/rdv/inviteEtablissementParcoursupToPremiumFollowUp.ts +++ b/server/src/jobs/rdv/inviteEtablissementParcoursupToPremiumFollowUp.ts @@ -1,8 +1,8 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { createRdvaPremiumParcoursupPageLink } from "@/services/appLinks.service" import { logger } from "../../common/logger" -import { EligibleTrainingsForAppointment, Etablissement } from "../../common/model/index" import { isValidEmail } from "../../common/utils/isValidEmail" import { notifyToSlack } from "../../common/utils/slackUtils" import config from "../../config" @@ -29,37 +29,39 @@ export const inviteEtablissementParcoursupToPremiumFollowUp = async (bypassDate: clause = [{ premium_invitation_date: { $ne: null } }] } - const etablissementsToInviteToPremium: Array = await Etablissement.aggregate([ - { - $match: { - gestionnaire_email: { - $ne: null, + const etablissementsToInviteToPremium: Array = (await getDbCollection("etablissements") + .aggregate([ + { + $match: { + gestionnaire_email: { + $ne: null, + }, + premium_activation_date: null, + premium_refusal_date: null, + premium_follow_up_date: null, + $and: clause, }, - premium_activation_date: null, - premium_refusal_date: null, - premium_follow_up_date: null, - $and: clause, }, - }, - { - $group: { - _id: { - gestionnaire_siret: "$gestionnaire_siret", + { + $group: { + _id: { + gestionnaire_siret: "$gestionnaire_siret", + }, + id: { $first: "$_id" }, + optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, + gestionnaire_email: { $first: "$gestionnaire_email" }, + count: { $sum: 1 }, }, - id: { $first: "$_id" }, - optout_activation_scheduled_date: { $first: "$optout_activation_scheduled_date" }, - gestionnaire_email: { $first: "$gestionnaire_email" }, - count: { $sum: 1 }, }, - }, - ]) + ]) + .toArray()) as Array for (const etablissement of etablissementsToInviteToPremium) { - const hasOneAvailableFormation = await EligibleTrainingsForAppointment.findOne({ + const hasOneAvailableFormation = await getDbCollection("eligible_trainings_for_appointments").findOne({ etablissement_gestionnaire_siret: etablissement._id.gestionnaire_siret, lieu_formation_email: { $ne: null }, parcoursup_visible: true, - }).lean() + }) if (!hasOneAvailableFormation || !etablissement.gestionnaire_email || !isValidEmail(etablissement.gestionnaire_email) || !etablissement._id.gestionnaire_siret) { continue @@ -87,11 +89,13 @@ export const inviteEtablissementParcoursupToPremiumFollowUp = async (bypassDate: }, }) - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( { gestionnaire_siret: etablissement._id.gestionnaire_siret }, { - premium_follow_up_date: dayjs().toDate(), - to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + $set: { + premium_follow_up_date: dayjs().toDate(), + to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + }, } ) } diff --git a/server/src/jobs/rdv/inviteEtablissementToOptOut.ts b/server/src/jobs/rdv/inviteEtablissementToOptOut.ts index ece218b8ce..b246a0fa10 100644 --- a/server/src/jobs/rdv/inviteEtablissementToOptOut.ts +++ b/server/src/jobs/rdv/inviteEtablissementToOptOut.ts @@ -1,8 +1,8 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { createRdvaOptOutUnsubscribePageLink } from "@/services/appLinks.service" import { logger } from "../../common/logger" -import { Etablissement } from "../../common/model/index" import { notifyToSlack } from "../../common/utils/slackUtils" import config from "../../config" import dayjs from "../../services/dayjs.service" @@ -25,24 +25,26 @@ export const inviteEtablissementToOptOut = async () => { logger.info("Cron #inviteEtablissementToOptOut started.") // Opt-out etablissement to activate - const etablissementsWithouOptMode: Array = await Etablissement.aggregate([ - { - $match: { - optout_invitation_date: null, - gestionnaire_email: { $ne: null }, + const etablissementsWithouOptMode: Array = (await getDbCollection("etablissements") + .aggregate([ + { + $match: { + optout_invitation_date: null, + gestionnaire_email: { $ne: null }, + }, }, - }, - { - $group: { - _id: { - gestionnaire_siret: "$gestionnaire_siret", + { + $group: { + _id: { + gestionnaire_siret: "$gestionnaire_siret", + }, + id: { $first: "$_id" }, + gestionnaire_email: { $first: "$gestionnaire_email" }, + count: { $sum: 1 }, }, - id: { $first: "$_id" }, - gestionnaire_email: { $first: "$gestionnaire_email" }, - count: { $sum: 1 }, }, - }, - ]) + ]) + .toArray()) as Array const willBeActivatedAt = dayjs().add(15, "days") logger.info(`Etablissements to invite: ${etablissementsWithouOptMode.length}`) @@ -71,12 +73,14 @@ export const inviteEtablissementToOptOut = async () => { }, }) - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( { gestionnaire_siret: etablissement._id.gestionnaire_siret }, { - optout_invitation_date: dayjs().toDate(), - optout_activation_scheduled_date: willBeActivatedAt.toDate(), - to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + $set: { + optout_invitation_date: dayjs().toDate(), + optout_activation_scheduled_date: willBeActivatedAt.toDate(), + to_CFA_invite_optout_last_message_id: emailEtablissement.messageId, + }, } ) } diff --git a/server/src/jobs/rdv/oneTimeJob/addLastActionDateToUserCollection.ts b/server/src/jobs/rdv/oneTimeJob/addLastActionDateToUserCollection.ts deleted file mode 100644 index 846915643d..0000000000 --- a/server/src/jobs/rdv/oneTimeJob/addLastActionDateToUserCollection.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { EApplicantRole } from "shared/constants/rdva" - -import { User } from "../../../common/model/index" -import dayjs from "../../../services/dayjs.service" -import { runScript } from "../../scriptWrapper" - -export const addLastActionDateToUserCollection = async () => { - const date = dayjs().format() - - const result = await User.updateMany( - { role: EApplicantRole.CANDIDAT }, - { - $set: { - last_action_date: date, - is_anonymized: false, - }, - } - ) - - return result.upserted -} - -runScript(async () => await addLastActionDateToUserCollection()) diff --git a/server/src/jobs/rdv/oneTimeJob/addNewFieldToAppointmentCollection.ts b/server/src/jobs/rdv/oneTimeJob/addNewFieldToAppointmentCollection.ts index f2f95ceb27..4edf86564d 100644 --- a/server/src/jobs/rdv/oneTimeJob/addNewFieldToAppointmentCollection.ts +++ b/server/src/jobs/rdv/oneTimeJob/addNewFieldToAppointmentCollection.ts @@ -1,8 +1,8 @@ -import { Appointment } from "../../../common/model/index" +import { getDbCollection } from "../../../common/utils/mongodbUtils" import { runScript } from "../../scriptWrapper" export const addNewFieldToAppointmentCollection = async () => { - const result = await Appointment.updateMany( + const result = await getDbCollection("appointments").updateMany( {}, { $set: { @@ -11,7 +11,7 @@ export const addNewFieldToAppointmentCollection = async () => { } ) - return result.upserted + return result.upsertedCount } runScript(async () => await addNewFieldToAppointmentCollection()) diff --git a/server/src/jobs/rdv/oneTimeJob/fixDuplicateUsers.ts b/server/src/jobs/rdv/oneTimeJob/fixDuplicateUsers.ts index de6cc91786..df047193fc 100644 --- a/server/src/jobs/rdv/oneTimeJob/fixDuplicateUsers.ts +++ b/server/src/jobs/rdv/oneTimeJob/fixDuplicateUsers.ts @@ -1,7 +1,8 @@ import { IUser } from "shared" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../../common/logger" -import { Appointment, User } from "../../../common/model" const findDuplicates = (users) => { const emailMap: { [key: string]: IUser[] } = {} @@ -25,14 +26,14 @@ const findDuplicates = (users) => { export const fixDuplicateUsers = async () => { logger.info(`Start user deduplication`) - const users = await User.find({}).lean() + const users = await getDbCollection("users").find({}).toArray() const duplicates: Iterable = findDuplicates(users) for await (const groupOfUsers of duplicates) { const userToKeep = groupOfUsers.shift() for await (const group of groupOfUsers) { - await Appointment.updateMany({ applicant_id: group._id.toString() }, { $set: { applicant_id: userToKeep?._id.toString() } }) - await User.findByIdAndDelete(group._id) + await getDbCollection("appointments").updateMany({ applicant_id: group._id.toString() }, { $set: { applicant_id: userToKeep?._id.toString() } }) + await getDbCollection("users").deleteOne({ _id: group._id }) } } logger.info(`End user deduplication`) diff --git a/server/src/jobs/rdv/oneTimeJob/repriseEmailsRdv.ts b/server/src/jobs/rdv/oneTimeJob/repriseEmailsRdv.ts deleted file mode 100644 index e3d8a86e79..0000000000 --- a/server/src/jobs/rdv/oneTimeJob/repriseEmailsRdv.ts +++ /dev/null @@ -1,62 +0,0 @@ -import Boom from "boom" - -import { logger } from "../../../common/logger" -import { getReferrerByKeyName } from "../../../common/model/constants/referrers" -import { Appointment, Etablissement, User } from "../../../common/model/index" -import { asyncForEach } from "../../../common/utils/asyncUtils" -import { sentryCaptureException } from "../../../common/utils/sentryUtils" -import { notifyToSlack } from "../../../common/utils/slackUtils" -import { sendFormateurAppointmentEmail } from "../../../services/appointment.service" -import dayjs from "../../../services/dayjs.service" -import * as eligibleTrainingsForAppointmentService from "../../../services/eligibleTrainingsForAppointment.service" - -export const repriseEmailRdvs = async ({ fromDateStr }: { fromDateStr: string }) => { - const dateFormat = "DD-MM-YYYY" - const dayjsDate = dayjs(fromDateStr, dateFormat) - if (!dayjsDate.isValid()) { - throw Boom.internal(`invalid date: ${fromDateStr}. Valid format is ${dateFormat}`) - } - const fromDate = dayjsDate.toDate() - logger.info(`Reprise des emails de rdv: récupération des rdvs depuis le ${fromDate.toISOString()}...`) - const appointments = await Appointment.find({ created_at: { $gt: fromDate } }).lean() - logger.info(`Reprise des emails de rdv: ${appointments.length} rdvs à envoyer`) - const stats = { success: 0, failure: 0 } - - await asyncForEach(appointments, async (appointment) => { - try { - const user = await User.findOne({ _id: appointment.applicant_id }) - const referrerObj = getReferrerByKeyName(appointment.appointment_origin) - const eligibleTrainingsForAppointment = await eligibleTrainingsForAppointmentService.findOne({ - cle_ministere_educatif: appointment.cle_ministere_educatif, - referrers: { $in: [referrerObj.name] }, - }) - const etablissement = await Etablissement.findOne({ - formateur_siret: eligibleTrainingsForAppointment?.etablissement_formateur_siret, - }) - - if (!user || !eligibleTrainingsForAppointment || !etablissement) { - logger.error(`user, eligibleTrainingsForAppointment ou etablissement manquant pour appointmentId=${appointment._id}`) - stats.failure++ - return - } - - const subjectPrefix = "[Erratum]" - // doit être appelé en premier pour valider l'envoi de mail au formateur - await sendFormateurAppointmentEmail(user, appointment, eligibleTrainingsForAppointment, referrerObj, etablissement, subjectPrefix) - // await sendCandidateAppointmentEmail(user, appointment, eligibleTrainingsForAppointment, referrerObj, subjectPrefix) - stats.success++ - } catch (err: any) { - const errorMessage = (err && "message" in err && err.message) || err - logger.error(err) - logger.error(`Reprise des emails de rdv: rdv id=${appointment._id}, erreur: ${errorMessage}`) - sentryCaptureException(err) - stats.failure++ - } - }) - await notifyToSlack({ - subject: "Reprise des emails de rdv", - message: `${stats.success} rdvs repris avec succès. ${stats.failure} rdvs ont rencontré une erreur.`, - error: stats.failure > 0, - }) - return stats -} diff --git a/server/src/jobs/rdv/premiumActivatedReminder.ts b/server/src/jobs/rdv/premiumActivatedReminder.ts index 86f1464597..d2fcfe8c50 100644 --- a/server/src/jobs/rdv/premiumActivatedReminder.ts +++ b/server/src/jobs/rdv/premiumActivatedReminder.ts @@ -1,7 +1,7 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { logger } from "../../common/logger" -import { Etablissement } from "../../common/model/index" import { isValidEmail } from "../../common/utils/isValidEmail" import config from "../../config" import dayjs from "../../services/dayjs.service" @@ -16,15 +16,17 @@ export const premiumActivatedReminder = async () => { logger.info("Cron #premiumActivatedReminder started.") const [etablissementsActivated, eligibleTrainingsForAppointmentsFound] = await Promise.all([ - Etablissement.find({ - gestionnaire_email: { - $ne: null, - }, - premium_activation_date: { - $ne: null, - }, - }).lean(), - eligibleTrainingsForAppointmentService.find({ parcoursup_id: { $ne: null }, lieu_formation_email: { $ne: null } }).lean(), + getDbCollection("etablissements") + .find({ + gestionnaire_email: { + $ne: null, + }, + premium_activation_date: { + $ne: null, + }, + }) + .toArray(), + eligibleTrainingsForAppointmentService.find({ parcoursup_id: { $ne: null }, lieu_formation_email: { $ne: null } }), ]) const etablissementWithParcoursup = etablissementsActivated.filter((etablissement) => @@ -84,10 +86,12 @@ export const premiumActivatedReminder = async () => { }, }) - await Etablissement.updateOne( + await getDbCollection("etablissements").updateOne( { formateur_siret: etablissement.formateur_siret }, { - premium_invitation_date: dayjs().toDate(), + $set: { + premium_invitation_date: dayjs().toDate(), + }, } ) } catch (error) { diff --git a/server/src/jobs/rdv/premiumInviteOneShot.ts b/server/src/jobs/rdv/premiumInviteOneShot.ts index cef983da7d..488f9f7acf 100644 --- a/server/src/jobs/rdv/premiumInviteOneShot.ts +++ b/server/src/jobs/rdv/premiumInviteOneShot.ts @@ -1,7 +1,7 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { logger } from "../../common/logger" -import { Etablissement } from "../../common/model/index" import { isValidEmail } from "../../common/utils/isValidEmail" import config from "../../config" import dayjs from "../../services/dayjs.service" @@ -16,16 +16,18 @@ export const premiumInviteOneShot = async () => { logger.info("Cron #premiumInviteOneShot started.") const [etablissementsActivated, eligibleTrainingsForAppointmentsFound] = await Promise.all([ - Etablissement.find({ - gestionnaire_email: { - $ne: null, - }, - optout_activation_date: { - $ne: null, - }, - premium_activation_date: null, - }).lean(), - eligibleTrainingsForAppointmentService.find({ parcoursup_id: { $ne: null }, lieu_formation_email: { $ne: null } }).lean(), + getDbCollection("etablissements") + .find({ + gestionnaire_email: { + $ne: null, + }, + optout_activation_date: { + $ne: null, + }, + premium_activation_date: null, + }) + .toArray(), + eligibleTrainingsForAppointmentService.find({ parcoursup_id: { $ne: null }, lieu_formation_email: { $ne: null } }), ]) const etablissementWithParcoursup = etablissementsActivated.filter((etablissement) => @@ -73,10 +75,12 @@ export const premiumInviteOneShot = async () => { }, }) - await Etablissement.updateOne( + await getDbCollection("etablissements").updateOne( { formateur_siret: etablissement.formateur_siret }, { - premium_invitation_date: dayjs().toDate(), + $set: { + premium_invitation_date: dayjs().toDate(), + }, } ) } catch (error) { diff --git a/server/src/jobs/rdv/removeDuplicateEtablissements.ts b/server/src/jobs/rdv/removeDuplicateEtablissements.ts index 47bf5f6cc2..3d1d618851 100644 --- a/server/src/jobs/rdv/removeDuplicateEtablissements.ts +++ b/server/src/jobs/rdv/removeDuplicateEtablissements.ts @@ -1,7 +1,8 @@ import { IEtablissement } from "shared" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { Etablissement } from "../../common/model" import { asyncForEach } from "../../common/utils/asyncUtils" function findDocumentWithMostFields(documents: Array>): Partial | null { @@ -27,29 +28,31 @@ function findDocumentWithMostFields(documents: Array>): } export const removeDuplicateEtablissements = async () => { - const duplicates: Array<{ duplicateDocuments: Partial[] }> = await Etablissement.aggregate([ - { - $group: { - _id: { - gestionnaire_siret: "$gestionnaire_siret", - formateur_siret: "$formateur_siret", + const duplicates: Array<{ duplicateDocuments: Partial[] }> = (await getDbCollection("etablissements") + .aggregate([ + { + $group: { + _id: { + gestionnaire_siret: "$gestionnaire_siret", + formateur_siret: "$formateur_siret", + }, + count: { $sum: 1 }, + documents: { $push: "$$ROOT" }, }, - count: { $sum: 1 }, - documents: { $push: "$$ROOT" }, }, - }, - { - $match: { - count: { $gt: 1 }, + { + $match: { + count: { $gt: 1 }, + }, }, - }, - { - $project: { - _id: 0, - duplicateDocuments: "$documents", + { + $project: { + _id: 0, + duplicateDocuments: "$documents", + }, }, - }, - ]) + ]) + .toArray()) as Array<{ duplicateDocuments: Partial[] }> if (!duplicates.length) return logger.info(`${duplicates.length} etablissements duplicated to control`) @@ -58,6 +61,6 @@ export const removeDuplicateEtablissements = async () => { const documentToKeep = findDocumentWithMostFields(duplicate.duplicateDocuments) if (!documentToKeep) return const documentsToRemove = duplicate.duplicateDocuments.filter((doc) => doc._id != documentToKeep._id) - await Promise.all(documentsToRemove.map(async (etablissement) => await Etablissement.findByIdAndDelete(etablissement._id))) + await Promise.all(documentsToRemove.map(async (etablissement) => await getDbCollection("etablissements").deleteOne({ _id: etablissement._id }))) }) } diff --git a/server/src/jobs/rdv/syncEtablissementDates.ts b/server/src/jobs/rdv/syncEtablissementDates.ts index 921fe0d5d4..35d595b9ec 100644 --- a/server/src/jobs/rdv/syncEtablissementDates.ts +++ b/server/src/jobs/rdv/syncEtablissementDates.ts @@ -1,7 +1,8 @@ import { isEmpty } from "lodash-es" import { IEtablissement } from "shared" -import { Etablissement } from "../../common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { notifyToSlack } from "../../common/utils/slackUtils" function findEarliestDates(objectsArray) { @@ -48,52 +49,54 @@ type IEtablissementByGestionnaireSiret = Array<{ }> export const syncEtablissementDates = async () => { - const etablissementByGestionnaireSiret: IEtablissementByGestionnaireSiret = await Etablissement.aggregate([ - { - $group: { - _id: "$gestionnaire_siret", - documents: { $push: "$$ROOT" }, - count: { $sum: 1 }, + const etablissementByGestionnaireSiret: IEtablissementByGestionnaireSiret = (await getDbCollection("etablissements") + .aggregate([ + { + $group: { + _id: "$gestionnaire_siret", + documents: { $push: "$$ROOT" }, + count: { $sum: 1 }, + }, }, - }, - { - $match: { - count: { $gt: 1 }, + { + $match: { + count: { $gt: 1 }, + }, }, - }, - { - $project: { - _id: 1, - documents: { - $map: { - input: "$documents", - as: "doc", - in: { - _id: "$$doc._id", - premium_invitation_date: "$$doc.premium_invitation_date", - premium_activation_date: "$$doc.premium_activation_date", - premium_refusal_date: "$$doc.premium_refusal_date", - premium_follow_up_date: "$$doc.premium_follow_up_date", - premium_affelnet_invitation_date: "$$doc.premium_affelnet_invitation_date", - premium_affelnet_activation_date: "$$doc.premium_affelnet_activation_date", - premium_affelnet_refusal_date: "$$doc.premium_affelnet_refusal_date", - premium_affelnet_follow_up_date: "$$doc.premium_affelnet_follow_up_date", - optout_invitation_date: "$$doc.optout_invitation_date", - optout_activation_date: "$$doc.optout_activation_date", - optout_activation_scheduled_date: "$$doc.optout_activation_scheduled_date", - optout_refusal_date: "$$doc.optout_refusal_date", + { + $project: { + _id: 1, + documents: { + $map: { + input: "$documents", + as: "doc", + in: { + _id: "$$doc._id", + premium_invitation_date: "$$doc.premium_invitation_date", + premium_activation_date: "$$doc.premium_activation_date", + premium_refusal_date: "$$doc.premium_refusal_date", + premium_follow_up_date: "$$doc.premium_follow_up_date", + premium_affelnet_invitation_date: "$$doc.premium_affelnet_invitation_date", + premium_affelnet_activation_date: "$$doc.premium_affelnet_activation_date", + premium_affelnet_refusal_date: "$$doc.premium_affelnet_refusal_date", + premium_affelnet_follow_up_date: "$$doc.premium_affelnet_follow_up_date", + optout_invitation_date: "$$doc.optout_invitation_date", + optout_activation_date: "$$doc.optout_activation_date", + optout_activation_scheduled_date: "$$doc.optout_activation_scheduled_date", + optout_refusal_date: "$$doc.optout_refusal_date", + }, }, }, }, }, - }, - ]) + ]) + .toArray()) as IEtablissementByGestionnaireSiret if (etablissementByGestionnaireSiret.length) { for await (const etablissement of etablissementByGestionnaireSiret) { const earliestDates = findEarliestDates(etablissement.documents) if (!isEmpty(earliestDates)) { - await Etablissement.updateMany({ gestionnaire_siret: etablissement._id }, { $set: earliestDates }) + await getDbCollection("etablissements").updateMany({ gestionnaire_siret: etablissement._id }, { $set: earliestDates }) } } } diff --git a/server/src/jobs/rdv/syncEtablissementsAndFormations.ts b/server/src/jobs/rdv/syncEtablissementsAndFormations.ts index 3c8c53907e..67df42d5e1 100644 --- a/server/src/jobs/rdv/syncEtablissementsAndFormations.ts +++ b/server/src/jobs/rdv/syncEtablissementsAndFormations.ts @@ -1,9 +1,11 @@ +import { ObjectId } from "mongodb" import { oleoduc, writeData } from "oleoduc" import { referrers } from "shared/constants/referers" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { Etablissement, FormationCatalogue, ReferentielOnisep } from "../../common/model/index" -import { create, findOne, getEmailForRdv, updateParameter } from "../../services/eligibleTrainingsForAppointment.service" +import { create, getEmailForRdv } from "../../services/eligibleTrainingsForAppointment.service" import { findFirstNonBlacklistedEmail } from "../../services/formation.service" const hasDateProperty = (etablissements, propertyName) => { @@ -18,31 +20,37 @@ export const syncEtablissementsAndFormations = async () => { logger.info("Cron #syncEtablissementsAndFormations started.") await oleoduc( - FormationCatalogue.find({ + getDbCollection("formationcatalogues").find({ cle_ministere_educatif: { $ne: null }, - }).cursor(), + }), writeData( async (formation) => { const [eligibleTrainingsForAppointment, etablissements, existInReferentielOnisep] = await Promise.all([ - findOne({ - cle_ministere_educatif: formation.cle_ministere_educatif, - }) - .select({ lieu_formation_email: 1, is_lieu_formation_email_customized: 1 }) - .lean(), - Etablissement.find({ - gestionnaire_siret: formation.etablissement_gestionnaire_siret, - }) - .select({ - premium_affelnet_activation_date: 1, - optout_refusal_date: 1, - optout_activation_date: 1, - premium_refusal_date: 1, - premium_activation_date: 1, - premium_affelnet_refusal_date: 1, - gestionnaire_email: 1, - }) - .lean(), - ReferentielOnisep.findOne({ cle_ministere_educatif: formation.cle_ministere_educatif }).lean(), + getDbCollection("eligible_trainings_for_appointments").findOne( + { + cle_ministere_educatif: formation.cle_ministere_educatif, + }, + { projection: { lieu_formation_email: 1, is_lieu_formation_email_customized: 1 } } + ), + getDbCollection("etablissements") + .find( + { + gestionnaire_siret: formation.etablissement_gestionnaire_siret, + }, + { + projection: { + premium_affelnet_activation_date: 1, + optout_refusal_date: 1, + optout_activation_date: 1, + premium_refusal_date: 1, + premium_activation_date: 1, + premium_affelnet_refusal_date: 1, + gestionnaire_email: 1, + }, + } + ) + .toArray(), + getDbCollection("referentieloniseps").findOne({ cle_ministere_educatif: formation.cle_ministere_educatif }), ]) const hasPremiumAffelnetActivation = hasDateProperty(etablissements, "premium_affelnet_activation_date") @@ -88,25 +96,27 @@ export const syncEtablissementsAndFormations = async () => { }) } - await updateParameter(eligibleTrainingsForAppointment._id, { - training_id_catalogue: formation._id, - lieu_formation_email: emailRdv, - parcoursup_id: formation.parcoursup_id, - parcoursup_visible: formation.parcoursup_visible, - affelnet_visible: formation.affelnet_visible, - training_code_formation_diplome: formation.cfd, - etablissement_formateur_zip_code: formation.etablissement_formateur_code_postal, - training_intitule_long: formation.intitule_long, - referrers: referrersToActivate, - is_catalogue_published: formation.published, - last_catalogue_sync_date: new Date(), - lieu_formation_street: formation.lieu_formation_adresse, - lieu_formation_city: formation.localite, - lieu_formation_zip_code: formation.code_postal, - etablissement_formateur_raison_sociale: formation.etablissement_formateur_entreprise_raison_sociale, - etablissement_formateur_street: formation.etablissement_formateur_adresse, - departement_etablissement_formateur: formation.etablissement_formateur_nom_departement, - etablissement_formateur_city: formation.etablissement_formateur_localite, + await getDbCollection("eligible_trainings_for_appointments").updateOne(eligibleTrainingsForAppointment._id, { + $set: { + training_id_catalogue: formation._id, + lieu_formation_email: emailRdv, + parcoursup_id: formation.parcoursup_id, + parcoursup_visible: formation.parcoursup_visible, + affelnet_visible: formation.affelnet_visible, + training_code_formation_diplome: formation.cfd, + etablissement_formateur_zip_code: formation.etablissement_formateur_code_postal, + training_intitule_long: formation.intitule_long, + referrers: referrersToActivate, + is_catalogue_published: formation.published, + last_catalogue_sync_date: new Date(), + lieu_formation_street: formation.lieu_formation_adresse, + lieu_formation_city: formation.localite, + lieu_formation_zip_code: formation.code_postal, + etablissement_formateur_raison_sociale: formation.etablissement_formateur_entreprise_raison_sociale, + etablissement_formateur_street: formation.etablissement_formateur_adresse, + departement_etablissement_formateur: formation.etablissement_formateur_nom_departement, + etablissement_formateur_city: formation.etablissement_formateur_localite, + }, }) } else { const emailRdv = await getEmailForRdv({ @@ -119,6 +129,10 @@ export const syncEtablissementsAndFormations = async () => { if (!emailRdv) return await create({ + _id: new ObjectId(), + created_at: new Date(), + last_catalogue_sync_date: new Date(), + rco_formation_id: formation.id_rco_formation, training_id_catalogue: formation._id, lieu_formation_email: emailRdv, parcoursup_id: formation.parcoursup_id, @@ -149,17 +163,19 @@ export const syncEtablissementsAndFormations = async () => { ) } - await Etablissement.updateMany( + await getDbCollection("etablissements").updateMany( { $and: [{ formateur_siret: formation.etablissement_formateur_siret, gestionnaire_siret: formation.etablissement_gestionnaire_siret }] }, { - gestionnaire_siret: formation.etablissement_gestionnaire_siret, - gestionnaire_email: gestionnaireEmail, - raison_sociale: formation.etablissement_formateur_entreprise_raison_sociale, - formateur_siret: formation.etablissement_formateur_siret, - formateur_address: formation.etablissement_formateur_adresse, - formateur_zip_code: formation.etablissement_formateur_code_postal, - formateur_city: formation.etablissement_formateur_localite, - last_catalogue_sync_date: new Date(), + $set: { + gestionnaire_siret: formation.etablissement_gestionnaire_siret, + gestionnaire_email: gestionnaireEmail, + raison_sociale: formation.etablissement_formateur_entreprise_raison_sociale, + formateur_siret: formation.etablissement_formateur_siret, + formateur_address: formation.etablissement_formateur_adresse, + formateur_zip_code: formation.etablissement_formateur_code_postal, + formateur_city: formation.etablissement_formateur_localite, + last_catalogue_sync_date: new Date(), + }, }, { upsert: true, diff --git a/server/src/jobs/rdv/syncEtablissementsAndFormationsNextVersion.ts b/server/src/jobs/rdv/syncEtablissementsAndFormationsNextVersion.ts index ac89463734..502800114d 100644 --- a/server/src/jobs/rdv/syncEtablissementsAndFormationsNextVersion.ts +++ b/server/src/jobs/rdv/syncEtablissementsAndFormationsNextVersion.ts @@ -1,10 +1,11 @@ +// @ts-ignore import { oleoduc, writeData } from "oleoduc" import { IEligibleTrainingsForAppointment, IEtablissement } from "shared" import { referrers } from "shared/constants/referers" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { logger } from "../../common/logger" -import { Etablissement, FormationCatalogue, ReferentielOnisep } from "../../common/model/index" -import { db } from "../../common/mongodb" import { asyncForEach } from "../../common/utils/asyncUtils" import { isValidEmail } from "../../common/utils/isValidEmail" import { isEmailBlacklisted } from "../../services/application.service" @@ -13,7 +14,7 @@ import { getMostFrequentEmailByGestionnaireSiret } from "../../services/formatio import { removeDuplicateEtablissements } from "./removeDuplicateEtablissements" const prepareETFA = async () => { - await FormationCatalogue.aggregate([ + await getDbCollection("formationcatalogues").aggregate([ { $project: { training_id_catalogue: "$_id", @@ -65,18 +66,17 @@ const prepareETFA = async () => { } const updateLieuFormationEmail = async () => { - const etfa: IEligibleTrainingsForAppointment[] = await db - .collection("eligible_trainings_for_appointments") + const etfa = (await getDbCollection("eligible_trainings_for_appointments") .find({}) .project({ etablissement_gestionnaire_siret: 1, lieu_formation_email: 1 }) - .toArray() + .toArray()) as IEligibleTrainingsForAppointment[] await Promise.all( etfa.map(async (formation) => { if (!formation.etablissement_gestionnaire_siret) return if (!formation.lieu_formation_email) { const email = await getMostFrequentEmailByGestionnaireSiret(formation.etablissement_gestionnaire_siret, "email") if (!email) return - await db.collection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: formation._id }, { $set: { lieu_formation_email: email } }) + await getDbCollection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: formation._id }, { $set: { lieu_formation_email: email } }) return } if (isValidEmail(formation.lieu_formation_email) && !(await isEmailBlacklisted(formation.lieu_formation_email))) { @@ -84,7 +84,7 @@ const updateLieuFormationEmail = async () => { } else { const email = await getMostFrequentEmailByGestionnaireSiret(formation.etablissement_gestionnaire_siret, "email") if (!email) return - await db.collection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: formation._id }, { $set: { lieu_formation_email: email } }) + await getDbCollection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: formation._id }, { $set: { lieu_formation_email: email } }) return } }) @@ -99,20 +99,22 @@ const addReferrersToETFA = async () => { // .toArray() oleoduc( - db - .collection("eligible_trainings_for_appointments") + getDbCollection("eligible_trainings_for_appointments") .find({ lieu_formation_email: { $ne: null } }) .project({ cle_ministere_educatif: 1, etablissement_gestionnaire_siret: 1, parcoursup_visible: 1 }), writeData( async (formation) => { const [etablissements, existInReferentielOnisep] = await Promise.all([ - Etablissement.find({ - gestionnaire_siret: formation.etablissement_gestionnaire_siret, - $and: [{ optout_activation_date: { $exists: true, $ne: null } }, { premium_activation_date: { $exists: true, $ne: null } }], - }) - .select({ optout_activation_date: 1, premium_activation_date: 1 }) - .lean(), - ReferentielOnisep.findOne({ cle_ministere_educatif: formation.cle_ministere_educatif }).lean(), + getDbCollection("etablissements") + .find( + { + gestionnaire_siret: formation.etablissement_gestionnaire_siret, + $and: [{ optout_activation_date: { $exists: true, $ne: null } }, { premium_activation_date: { $exists: true, $ne: null } }], + }, + { projection: { optout_activation_date: 1, premium_activation_date: 1 } } + ) + .toArray(), + getDbCollection("referentieloniseps").findOne({ cle_ministere_educatif: formation.cle_ministere_educatif }), ]) const hasOptOutActivation = etablissements.some((etab) => etab.optout_activation_date !== null && etab.optout_activation_date !== undefined) const hasPremiumActivation = etablissements.some((etab) => etab.premium_activation_date !== null && etab.premium_activation_date !== undefined) @@ -132,7 +134,7 @@ const addReferrersToETFA = async () => { referrersToActivate.push(referrers.PARCOURSUP.name) } try { - await db.collection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: formation._id }, { $set: { referrers: referrersToActivate } }) + await getDbCollection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: formation._id }, { $set: { referrers: referrersToActivate } }) } catch (err) { console.error(err) } @@ -146,8 +148,7 @@ const addReferrersToETFA = async () => { const createMissingEtablissement = async () => { try { - await db - .collection("eligible_trainings_for_appointments") + await getDbCollection("eligible_trainings_for_appointments") .aggregate([ { $lookup: { @@ -194,11 +195,11 @@ const createMissingEtablissement = async () => { } const updateGestionnaireEmailEtablissement = async () => { - const etablissements: IEtablissement[] = await Etablissement.find({ gestionnaire_email: null }).lean() + const etablissements: IEtablissement[] = await getDbCollection("etablissements").find({ gestionnaire_email: null }).toArray() await asyncForEach(etablissements, async (etab) => { if (!etab.gestionnaire_siret) return const email = await getMostFrequentEmailByGestionnaireSiret(etab.gestionnaire_siret, "etablissement_gestionnaire_courriel") - await Etablissement.findByIdAndUpdate(etab._id, { $set: { gestionnaire_email: email, last_catalogue_sync_date: new Date() } }) + await getDbCollection("etablissements").updateOne({ _id: etab._id }, { $set: { gestionnaire_email: email, last_catalogue_sync_date: new Date() } }) }) } diff --git a/server/src/jobs/scriptWrapper.ts b/server/src/jobs/scriptWrapper.ts index 46f7df5333..dbe3157f17 100644 --- a/server/src/jobs/scriptWrapper.ts +++ b/server/src/jobs/scriptWrapper.ts @@ -4,7 +4,7 @@ import { isEmpty } from "lodash-es" import prettyMilliseconds from "pretty-ms" import { getLoggerWithContext } from "../common/logger" -import { closeMongoConnection } from "../common/mongodb" +import { closeMongodbConnection } from "../common/utils/mongodbUtils" import config from "../config" const logger = getLoggerWithContext("script") @@ -55,7 +55,7 @@ const exit = async (scriptError?: any) => { setTimeout(() => { //Waiting logger to flush all logs (MongoDB) - closeMongoConnection().catch((e) => { + closeMongodbConnection().catch((e) => { console.error(e) process.exitCode = 1 }) diff --git a/server/src/jobs/seed/ficheMetierRomev4/ficheMetierRomev4.ts b/server/src/jobs/seed/ficheMetierRomev4/ficheMetierRomev4.ts deleted file mode 100644 index fd34adb18f..0000000000 --- a/server/src/jobs/seed/ficheMetierRomev4/ficheMetierRomev4.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { getRomeV4DetailsFromFT, getRomeV4ListFromFT } from "@/common/apis/FranceTravail" -import { ReferentielRome } from "@/common/model" - -import { logger } from "../../../common/logger" -import { asyncForEach, delay } from "../../../common/utils/asyncUtils" - -export const importFichesRomeV4 = async () => { - const romeList = await getRomeV4ListFromFT() - - if (romeList && romeList.length > 500) { - logger.info(`${romeList.length} fiches métiers trouvées`) - - logger.info("Suppression des fiches métiers V4 courantes") - await ReferentielRome.deleteMany({}) - - logger.info("Insertion des fiches métiers V4") - - await asyncForEach(romeList, async (rome, index) => { - logger.info(`${index + 1}/${romeList.length} : insertion de ${rome.code}`) - const response = await getRomeV4DetailsFromFT(rome.code) - await ReferentielRome.create({ rome_code: rome.code, fiche_metier: response }) - await delay(1000) - }) - } else { - logger.info("Liste des fiches métiers non trouvées ou anormalement petite. Processus interrompu.") - } -} diff --git a/server/src/jobs/seed/referentielRome/referentielRome.ts b/server/src/jobs/seed/referentielRome/referentielRome.ts index d90f716aae..034e5efe03 100644 --- a/server/src/jobs/seed/referentielRome/referentielRome.ts +++ b/server/src/jobs/seed/referentielRome/referentielRome.ts @@ -1,13 +1,15 @@ import { readFileSync } from "fs" import iconv from "iconv-lite" +import { ObjectId } from "mongodb" +import { IReferentielRome } from "shared/index" import * as xml2j from "xml2js" -import { logger } from "@/common/logger.js" +import { logger } from "@/common/logger" +import { getDbCollection } from "@/common/utils/mongodbUtils" -import __dirname from "../../../common/dirname.js" -import { ReferentielRome } from "../../../common/model/index.js" -import { asyncForEach } from "../../../common/utils/asyncUtils.js" +import __dirname from "../../../common/dirname" +import { asyncForEach } from "../../../common/utils/asyncUtils" const getGenericItem = (genericItem: { libelle: string; items: { item: any | any[] } }) => { const tempsItems = !(genericItem.items.item instanceof Array) ? [genericItem.items.item] : genericItem.items.item @@ -124,11 +126,16 @@ export const importReferentielRome = async () => { if (data.fiches_metier.fiche_metier.length > 500) { logger.info("Suppression du référentiel courant") - await ReferentielRome.deleteMany({}) + await getDbCollection("referentielromes").deleteMany({}) await asyncForEach(data.fiches_metier.fiche_metier, async (ficheMetier: any) => { const fiche = formatRawData(ficheMetier) - await ReferentielRome.create(fiche) + // @ts-expect-error TODO lors du prochain import + const savedFiche: IReferentielRome = { + ...fiche, + _id: new ObjectId(), + } + await getDbCollection("referentielromes").insertOne(savedFiche) }) } else { logger.info("Liste des ROMEs anormalement petite. Processus interrompu.") diff --git a/server/src/jobs/updateBrevoBlockedEmails/updateBrevoBlockedEmails.ts b/server/src/jobs/updateBrevoBlockedEmails/updateBrevoBlockedEmails.ts index 50be9152e6..9d5b1d44e5 100644 --- a/server/src/jobs/updateBrevoBlockedEmails/updateBrevoBlockedEmails.ts +++ b/server/src/jobs/updateBrevoBlockedEmails/updateBrevoBlockedEmails.ts @@ -1,9 +1,9 @@ import SibApiV3Sdk from "sib-api-v3-sdk" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { processBlacklistedEmail } from "@/services/emails.service" import { logger } from "../../common/logger" -import { EmailBlacklist } from "../../common/model" import { sentryCaptureException } from "../../common/utils/sentryUtils" import { notifyToSlack } from "../../common/utils/slackUtils" import config from "../../config" @@ -11,7 +11,7 @@ import config from "../../config" const saveBlacklistEmails = async (contacts) => { for (let i = 0; i < contacts.length; ++i) { const email = contacts[i].email.toLowerCase() - const blackListedEmail = await EmailBlacklist.findOne({ email }) + const blackListedEmail = await getDbCollection("emailblacklists").findOne({ email }) if (!blackListedEmail) { await processBlacklistedEmail(email, "brevo_spam") } diff --git a/server/src/jobs/verifications/controlApplications.ts b/server/src/jobs/verifications/controlApplications.ts index f67c5dc94e..62453b8167 100644 --- a/server/src/jobs/verifications/controlApplications.ts +++ b/server/src/jobs/verifications/controlApplications.ts @@ -1,11 +1,11 @@ import dayjs from "shared/helpers/dayjs" -import { Application } from "../../common/model" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { notifyToSlack } from "../../common/utils/slackUtils" export const controlApplications = async () => { const timestamp = dayjs().subtract(1, "hour").toDate() - const countApplications = await Application.countDocuments({ created_at: { $gte: timestamp } }) + const countApplications = await getDbCollection("applications").countDocuments({ created_at: { $gte: timestamp } }) if (countApplications === 0) { await notifyToSlack({ subject: "Verification des candidatures", message: "Aucune candidature prise dans la dernière heure", error: true }) } diff --git a/server/src/jobs/verifications/controlAppointments.ts b/server/src/jobs/verifications/controlAppointments.ts index 205ad25e57..46d640b74f 100644 --- a/server/src/jobs/verifications/controlAppointments.ts +++ b/server/src/jobs/verifications/controlAppointments.ts @@ -1,11 +1,11 @@ import dayjs from "shared/helpers/dayjs" -import { Appointment } from "../../common/model" +import { getDbCollection } from "../../common/utils/mongodbUtils" import { notifyToSlack } from "../../common/utils/slackUtils" export const controlAppointments = async () => { const timestamp = dayjs().subtract(2, "hours").toDate() - const countAppointments = await Appointment.countDocuments({ created_at: { $gte: timestamp } }) + const countAppointments = await getDbCollection("appointments").countDocuments({ created_at: { $gte: timestamp } }) if (countAppointments === 0) { await notifyToSlack({ subject: "Verification des rendez-vous", message: "Aucun rendez-vous pris depuis 2 heures", error: true }) } diff --git a/server/src/main.ts b/server/src/main.ts index 33843ee31a..d10fe53a84 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,4 +1,4 @@ -import { connectToMongo } from "@/common/mongodb" +import { connectToMongodb } from "@/common/utils/mongodbUtils" import { startCLI } from "./commands" import { logger } from "./common/logger" @@ -9,8 +9,7 @@ process.on("uncaughtException", (err) => logger.error(err, "uncaughtException")) try { logger.warn("starting application") - await connectToMongo(config.mongodb.uri) - + await connectToMongodb(config.mongodb.uri) await startCLI() } catch (err) { logger.error(err, "startup error") diff --git a/server/src/security/accessTokenService.ts b/server/src/security/accessTokenService.ts index 67ca263dd0..e23876fd9c 100644 --- a/server/src/security/accessTokenService.ts +++ b/server/src/security/accessTokenService.ts @@ -1,5 +1,6 @@ import Boom from "boom" import jwt from "jsonwebtoken" +import { ObjectId } from "mongodb" import { PathParam, QueryString } from "shared/helpers/generateUri" import { IUserRecruteur } from "shared/models" import { IUserWithAccount } from "shared/models/userWithAccount.model" @@ -8,7 +9,7 @@ import { assertUnreachable } from "shared/utils" import { Jsonify } from "type-fest" import { AnyZodObject, z } from "zod" -import { UserWithAccount } from "@/common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sentryCaptureException } from "@/common/utils/sentryUtils" import config from "@/config" @@ -225,7 +226,7 @@ export async function parseAccessToken( ): Promise> { const token = verifyJwtToken(jwtToken) as IAccessToken if (token.identity.type === "IUserRecruteur") { - const user = await UserWithAccount.findOne({ _id: token.identity._id }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: new ObjectId(token.identity._id) }) if (!user) throw Boom.forbidden() diff --git a/server/src/security/authenticationService.ts b/server/src/security/authenticationService.ts index 440b29942b..445cc91cc3 100644 --- a/server/src/security/authenticationService.ts +++ b/server/src/security/authenticationService.ts @@ -8,12 +8,12 @@ import { IUserWithAccount } from "shared/models/userWithAccount.model" import { ISecuredRouteSchema, WithSecurityScheme } from "shared/routes/common.routes" import { Role, UserWithType } from "shared/security/permissions" -import { Credential } from "@/common/model" import config from "@/config" import { getSession } from "@/services/sessions.service" import { updateLastConnectionDate } from "@/services/userRecruteur.service" import { getUserWithAccountByEmail } from "@/services/userWithAccount.service" +import { getDbCollection } from "../common/utils/mongodbUtils" import { controlUserState } from "../services/login.service" import { ApiApprentissageTokenData, parseApiApprentissageToken } from "./accessApiApprentissageService" @@ -93,7 +93,7 @@ async function authApiKey(req: FastifyRequest): Promise => { const { cfa_delegated_siret, establishment_siret } = recruiter if (cfa_delegated_siret) { - const cfa = await Cfa.findOne({ siret: cfa_delegated_siret }).lean() + const cfa = await getDbCollection("cfas").findOne({ siret: cfa_delegated_siret }) if (!cfa) { throw Boom.internal(`could not find cfa for recruiter with id=${recruiter._id}`) } return { recruiter, type: CFA, cfa } } else { - const entreprise = await Entreprise.findOne({ siret: establishment_siret }).lean() + const entreprise = await getDbCollection("entreprises").findOne({ siret: establishment_siret }) if (!entreprise) { throw Boom.internal(`could not find entreprise for recruiter with id=${recruiter._id}`) } @@ -79,25 +79,33 @@ async function getRecruitersResource(schema: S, re await Promise.all( schema.securityScheme.resources.recruiter.map(async (recruiterDef): Promise => { if ("_id" in recruiterDef) { - const recruiterOpt = await Recruiter.findById(getAccessResourcePathValue(recruiterDef._id, req)).lean() + const recruiterOpt = await getDbCollection("recruiters").findOne({ _id: getAccessResourcePathValue(recruiterDef._id, req) }) return recruiterOpt ? [recruiterOpt] : [] } if ("establishment_id" in recruiterDef) { - return Recruiter.find({ - establishment_id: getAccessResourcePathValue(recruiterDef.establishment_id, req), - }).lean() + return getDbCollection("recruiters") + .find({ + establishment_id: getAccessResourcePathValue(recruiterDef.establishment_id, req), + }) + .toArray() } if ("email" in recruiterDef && "establishment_siret" in recruiterDef) { - return Recruiter.find({ - email: getAccessResourcePathValue(recruiterDef.email, req), - establishment_siret: getAccessResourcePathValue(recruiterDef.establishment_siret, req), - }).lean() + return getDbCollection("recruiters") + .find({ + email: getAccessResourcePathValue(recruiterDef.email, req), + establishment_siret: getAccessResourcePathValue(recruiterDef.establishment_siret, req), + }) + .toArray() } if ("opco" in recruiterDef) { - return Recruiter.find({ opco: getAccessResourcePathValue(recruiterDef.opco, req) }).lean() + return getDbCollection("recruiters") + .find({ opco: getAccessResourcePathValue(recruiterDef.opco, req) }) + .toArray() } if ("cfa_delegated_siret" in recruiterDef) { - return Recruiter.find({ cfa_delegated_siret: getAccessResourcePathValue(recruiterDef.cfa_delegated_siret, req) }).lean() + return getDbCollection("recruiters") + .find({ cfa_delegated_siret: getAccessResourcePathValue(recruiterDef.cfa_delegated_siret, req) }) + .toArray() } assertUnreachable(recruiterDef) @@ -117,7 +125,7 @@ async function getJobsResource(schema: S, req: IRe schema.securityScheme.resources.job.map(async (jobDef): Promise => { if ("_id" in jobDef) { const id = getAccessResourcePathValue(jobDef._id, req) - const recruiter = await Recruiter.findOne({ "jobs._id": id }).lean() + const recruiter = await getDbCollection("recruiters").findOne({ "jobs._id": id }) if (!recruiter) { return null @@ -146,7 +154,7 @@ async function getUserResource(schema: S, req: IRe await Promise.all( schema.securityScheme.resources.user.map(async (userDef) => { if ("_id" in userDef) { - const userOpt = await UserWithAccount.findOne({ _id: getAccessResourcePathValue(userDef._id, req) }).lean() + const userOpt = await getDbCollection("userswithaccounts").findOne({ _id: getAccessResourcePathValue(userDef._id, req) }) return userOpt ? { _id: userOpt._id.toString() } : null } assertUnreachable(userDef) @@ -164,14 +172,14 @@ async function getApplicationResource(schema: S, r schema.securityScheme.resources.application.map(async (applicationDef): Promise => { if ("_id" in applicationDef) { const id = getAccessResourcePathValue(applicationDef._id, req) - const application = await Application.findById(id).lean() + const application = await getDbCollection("applications").findOne({ _id: id }) if (!application) return null const { job_id } = application if (!job_id) { return { application } } - const recruiter = await Recruiter.findOne({ "jobs._id": job_id }).lean() + const recruiter = await getDbCollection("recruiters").findOne({ "jobs._id": job_id }) if (!recruiter) { return { application } } @@ -199,7 +207,7 @@ async function getEntrepriseResource(schema: S, re schema.securityScheme.resources.entreprise.map(async (entrepriseDef): Promise => { if ("siret" in entrepriseDef) { const siret = getAccessResourcePathValue(entrepriseDef.siret, req) - const entreprise = await Entreprise.findOne({ siret }).lean() + const entreprise = await getDbCollection("entreprises").findOne({ siret }) return entreprise ? { entreprise } : null } else if ("_id" in entrepriseDef) { const id = getAccessResourcePathValue(entrepriseDef._id, req) @@ -208,7 +216,7 @@ async function getEntrepriseResource(schema: S, re } catch (e) { return null } - const entreprise = await Entreprise.findById(id).lean() + const entreprise = await getDbCollection("entreprises").findOne({ _id: new ObjectId(id.toString()) }) return entreprise ? { entreprise } : null } diff --git a/server/src/services/appLinks.service.ts b/server/src/services/appLinks.service.ts index 3d73078e51..f59514f54f 100644 --- a/server/src/services/appLinks.service.ts +++ b/server/src/services/appLinks.service.ts @@ -399,7 +399,7 @@ export function generateOffreToken(user: IUserWithAccount, offre: IJob) { generateScope({ schema: zRoutes.post["/formulaire/offre/:jobId/delegation/by-token"], options: { - params: { jobId: offre._id }, + params: { jobId: offre._id.toString() }, querystring: undefined, }, }), diff --git a/server/src/services/application.service.ts b/server/src/services/application.service.ts index 95a512a5d3..2cb42eb275 100644 --- a/server/src/services/application.service.ts +++ b/server/src/services/application.service.ts @@ -1,8 +1,8 @@ import Boom from "boom" import { isEmailBurner } from "burner-email-providers" import Joi from "joi" -import type { EnforceDocument } from "mongoose" -import { IApplication, IJob, ILbaCompany, INewApplicationV2, IRecruiter, JOB_STATUS, ZApplication, assertUnreachable } from "shared" +import { ObjectId } from "mongodb" +import { IApplication, IJob, ILbaCompany, INewApplicationV2, IRecruiter, JOB_STATUS, assertUnreachable } from "shared" import { ApplicantIntention } from "shared/constants/application" import { BusinessErrorCodes } from "shared/constants/errorCodes" import { LBA_ITEM_TYPE, LBA_ITEM_TYPE_OLD, newItemTypeToOldItemType } from "shared/constants/lbaitem" @@ -13,10 +13,10 @@ import { INewApplicationV2NEWCompanySiret, INewApplicationV2NEWJobId } from "sha import { z } from "zod" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { UserForAccessToken, userWithAccountToUserForToken } from "@/security/accessTokenService" import { logger } from "../common/logger" -import { Application, EmailBlacklist, LbaCompany, Recruiter, UserWithAccount } from "../common/model" import { manageApiError } from "../common/utils/errorManager" import { sentryCaptureException } from "../common/utils/sentryUtils" import config from "../config" @@ -62,19 +62,19 @@ type ILbaJob = { type: LBA_ITEM_TYPE.RECRUTEURS_LBA; job: ILbaCompany; recruiter /** * @description Get applications by job id */ -export const getApplicationsByJobId = (job_id: IApplication["job_id"]) => Application.find({ job_id }).lean() +export const getApplicationsByJobId = (job_id: IApplication["job_id"]) => getDbCollection("applications").find({ job_id }).toArray() /** * @description Get applications count by job id */ -export const getApplicationCount = (job_id: IApplication["job_id"]) => Application.count({ job_id }).lean() +export const getApplicationCount = (job_id: IApplication["job_id"]) => getDbCollection("applications").countDocuments({ job_id }) /** * @description Check if an email if blacklisted. * @param {string} email - Email * @return {Promise} */ -export const isEmailBlacklisted = async (email: string): Promise => Boolean(await EmailBlacklist.countDocuments({ email })) +export const isEmailBlacklisted = async (email: string): Promise => Boolean(await getDbCollection("emailblacklists").countDocuments({ email })) /** * @description Add an email address to the blacklist collection. @@ -86,12 +86,14 @@ export const addEmailToBlacklist = async (email: string, blacklistingOrigin: str try { z.string().email().parse(email) - await EmailBlacklist.findOneAndUpdate( + await getDbCollection("emailblacklists").findOneAndUpdate( { email }, { - email, - blacklisting_origin: blacklistingOrigin, - $setOnInsert: { created_at: new Date() }, + $set: { + email, + blacklisting_origin: blacklistingOrigin, + $setOnInsert: { _id: new ObjectId(), created_at: new Date() }, + }, }, { upsert: true } ) @@ -108,10 +110,10 @@ export const addEmailToBlacklist = async (email: string, blacklistingOrigin: str * @returns {Promise} */ export const findApplicationByMessageId = async ({ messageId, email }: { messageId: string; email: string }) => - Application.findOne({ company_email: email, to_company_message_id: messageId }) + getDbCollection("applications").findOne({ company_email: email, to_company_message_id: messageId }) export const removeEmailFromLbaCompanies = async (email: string) => { - return await LbaCompany.updateMany({ email }, { email: "" }) + return await getDbCollection("bonnesboites").updateMany({ email }, { $set: { email: "" } }) } /** @@ -153,14 +155,14 @@ export const sendApplication = async ({ if (!recruteurEmail) { return { error: "email du recruteur manquant" } } - const application = newApplicationToApplicationDocument(newApplication, offreOrError, recruteurEmail) + const application = await newApplicationToApplicationDocument(newApplication, offreOrError, recruteurEmail) const fileContent = newApplication.applicant_file_content const { url: urlOfDetail, urlWithoutUtm: urlOfDetailNoUtm } = buildUrlsOfDetail(publicUrl, offreOrError) const recruiterEmailUrls = await buildRecruiterEmailUrls(application) const searched_for_job_label = newApplication.searched_for_job_label || "" - const buildTopic = (company_type: INewApplicationV2["company_type"], aJobTitle: string) => { + const buildTopic = (company_type: INewApplicationV2["company_type"], aJobTitle?: string | null) => { if (company_type === LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA) { return `Candidature en alternance - ${aJobTitle}` } else { @@ -174,7 +176,7 @@ export const sendApplication = async ({ subject: buildTopic(newApplication.company_type, application.job_title), template: getEmailTemplate("mail-candidature"), data: { - ...sanitizeApplicationForEmail(application.toObject()), + ...sanitizeApplicationForEmail(application), ...images, ...recruiterEmailUrls, searched_for_job_label: sanitizeForEmail(searched_for_job_label), @@ -192,7 +194,7 @@ export const sendApplication = async ({ to: application.applicant_email, subject: `Votre candidature chez ${application.company_name}`, template: getEmailTemplate(type === LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA ? "mail-candidat-matcha" : "mail-candidat"), - data: { ...sanitizeApplicationForEmail(application.toObject()), ...images, publicUrl, urlOfDetail, urlOfDetailNoUtm }, + data: { ...sanitizeApplicationForEmail(application), ...images, publicUrl, urlOfDetail, urlOfDetailNoUtm }, attachments: [ { filename: application.applicant_attachment_name, @@ -201,16 +203,14 @@ export const sendApplication = async ({ ], }) - application.to_applicant_message_id = emailCandidat.messageId + await getDbCollection("applications").findOneAndUpdate({ _id: application._id }, { $set: { to_applicant_message_id: emailCandidat.messageId } }) if (emailCompany?.accepted?.length) { - application.to_company_message_id = emailCompany.messageId + await getDbCollection("applications").findOneAndUpdate({ _id: application._id }, { $set: { to_company_message_id: emailCompany.messageId } }) } else { logger.info(`Application email rejected. applicant_email=${application.applicant_email} company_email=${application.company_email}`) throw new Error("Application email rejected") } - await application.save() - return { result: "ok", message: "messages sent" } } catch (err) { logger.error("Error sending application", err) @@ -245,7 +245,8 @@ export const sendApplicationV2 = async ({ } if ("company_siret" in newApplication) { - const LbaRecruteur = await LbaCompany.findOne({ siret: newApplication.company_siret, email: { $not: { $eq: null } } }).lean() // email can be null in collection + // email can be null in collection + const LbaRecruteur = await getDbCollection("bonnesboites").findOne({ siret: newApplication.company_siret, email: { $not: { $eq: null } } }) if (!LbaRecruteur) { throw Boom.badRequest(BusinessErrorCodes.NOTFOUND) } @@ -274,7 +275,7 @@ export const sendApplicationV2 = async ({ throw Boom.internal(BusinessErrorCodes.INTERNAL_EMAIL) } try { - const application = newApplicationToApplicationDocumentV2(newApplication, lbaJob, recruteurEmail, caller) + const application = await newApplicationToApplicationDocumentV2(newApplication, lbaJob, recruteurEmail, caller) const { url: urlOfDetail, urlWithoutUtm: urlOfDetailNoUtm } = buildUrlsOfDetail(publicUrl, lbaJob) const recruiterEmailUrls = await buildRecruiterEmailUrls(application) @@ -284,7 +285,7 @@ export const sendApplicationV2 = async ({ subject: type === LBA_ITEM_TYPE.RECRUTEURS_LBA ? `Candidature spontanée en alternance ${application.company_name}` : `Candidature en alternance - ${application.job_title}`, template: getEmailTemplate("mail-candidature"), data: { - ...sanitizeApplicationForEmail(application.toObject()), + ...sanitizeApplicationForEmail(application), ...images, ...recruiterEmailUrls, urlOfDetail, @@ -301,7 +302,7 @@ export const sendApplicationV2 = async ({ to: application.applicant_email, subject: `Votre candidature chez ${application.company_name}`, template: getEmailTemplate(type === LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA ? "mail-candidat-matcha" : "mail-candidat"), - data: { ...sanitizeApplicationForEmail(application.toObject()), ...images, publicUrl, urlOfDetail, urlOfDetailNoUtm }, + data: { ...sanitizeApplicationForEmail(application), ...images, publicUrl, urlOfDetail, urlOfDetailNoUtm }, attachments: [ { filename: application.applicant_attachment_name, @@ -311,15 +312,13 @@ export const sendApplicationV2 = async ({ }), ]) - application.to_applicant_message_id = emailCandidat.messageId + await getDbCollection("applications").findOneAndUpdate({ _id: application._id }, { $set: { to_applicant_message_id: emailCandidat.messageId } }) if (emailCompany?.accepted?.length) { - application.to_company_message_id = emailCompany.messageId + await getDbCollection("applications").findOneAndUpdate({ _id: application._id }, { $set: { to_company_message_id: emailCompany.messageId } }) } else { logger.info(`Application email rejected. applicant_email=${application.applicant_email} company_email=${application.company_email}`) throw Boom.internal("Email entreprise destinataire rejeté.") } - - await application.save() } catch (err) { sentryCaptureException(err) if (caller) { @@ -393,7 +392,7 @@ const buildReplyLink = (application: IApplication, intention: ApplicantIntention export const getUser2ManagingOffer = async (job: Pick): Promise => { const { managed_by } = job if (managed_by) { - const user = await UserWithAccount.findOne({ _id: managed_by }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: new ObjectId(managed_by) }) if (!user) { throw new Error(`could not find offer manager with id=${managed_by}`) } @@ -412,7 +411,7 @@ const buildRecruiterEmailUrls = async (application: IApplication) => { // get the related recruiters to fetch it's establishment_id let user: IUserWithAccount | undefined if (application.job_id) { - const recruiter = await Recruiter.findOne({ "jobs._id": application.job_id }).lean() + const recruiter = await getDbCollection("recruiters").findOne({ "jobs._id": new ObjectId(application.job_id) }) if (recruiter) { user = await getUser2ManagingOffer(getJobFromRecruiter(recruiter, application.job_id)) } @@ -439,12 +438,12 @@ const buildRecruiterEmailUrls = async (application: IApplication) => { return urls } -const offreOrCompanyToCompanyFields = (LbaJob: ILbaJob): Partial => { +const offreOrCompanyToCompanyFields = (LbaJob: ILbaJob) => { const { type } = LbaJob if (type === LBA_ITEM_TYPE.RECRUTEURS_LBA) { const { job } = LbaJob const { siret, enseigne, naf_label } = job - const application: Partial = { + const application = { company_siret: siret, company_name: enseigne, company_naf: naf_label, @@ -456,7 +455,7 @@ const offreOrCompanyToCompanyFields = (LbaJob: ILbaJob): Partial = const { job, recruiter } = LbaJob const { address, is_delegated, establishment_siret, establishment_enseigne, establishment_raison_sociale, naf_label } = recruiter const { rome_appellation_label, rome_label } = job - const application: Partial = { + const application = { company_siret: establishment_siret, company_name: establishment_enseigne || establishment_raison_sociale || "Enseigne inconnue", company_naf: naf_label ?? "", @@ -470,7 +469,7 @@ const offreOrCompanyToCompanyFields = (LbaJob: ILbaJob): Partial = } } -const cleanApplicantFields = (newApplication: INewApplicationV2): Partial => { +const cleanApplicantFields = (newApplication: INewApplicationV2) => { return { applicant_first_name: newApplication.applicant_first_name, applicant_last_name: newApplication.applicant_last_name, @@ -485,27 +484,34 @@ const cleanApplicantFields = (newApplication: INewApplicationV2): Partial { - const res = new Application({ +const newApplicationToApplicationDocument = async (newApplication: INewApplicationV2, offreOrCompany: ILbaJob, recruteurEmail: string) => { + const now = new Date() + const application: IApplication = { ...offreOrCompanyToCompanyFields(offreOrCompany), ...cleanApplicantFields(newApplication), company_email: recruteurEmail.toLowerCase(), job_origin: newApplication.company_type, - }) - ZApplication.parse(res.toObject()) - return res + _id: new ObjectId(), + created_at: now, + last_update_at: now, + to_applicant_message_id: null, + to_company_message_id: null, + } + await getDbCollection("applications").insertOne(application) + return application } /** * @description Initialize application object from query parameters */ -const newApplicationToApplicationDocumentV2 = ( +const newApplicationToApplicationDocumentV2 = async ( newApplication: INewApplicationV2NEWCompanySiret | INewApplicationV2NEWJobId, LbaJob: ILbaJob, recruteurEmail: string, caller?: string ) => { - const res = new Application({ + const now = new Date() + const application: IApplication = { ...offreOrCompanyToCompanyFields(LbaJob), applicant_first_name: newApplication.applicant_first_name, applicant_last_name: newApplication.applicant_last_name, @@ -516,9 +522,14 @@ const newApplicationToApplicationDocumentV2 = ( caller: caller, company_email: recruteurEmail.toLowerCase(), job_origin: LbaJob.type, - }) - ZApplication.parse(res.toObject()) - return res + _id: new ObjectId(), + created_at: now, + last_update_at: now, + to_applicant_message_id: null, + to_company_message_id: null, + } + await getDbCollection("applications").insertOne(application) + return application } /** @@ -552,7 +563,7 @@ export const validateJob = async (application: INewApplicationV2): Promise }): Promise => { +const notifyHardbounceToApplicant = async ({ application }: { application: IApplication | any }): Promise => { await mailer.sendEmail({ to: application.applicant_email, subject: `Votre candidature n'a pas pu être envoyée à ${application.company_name}`, @@ -783,7 +794,7 @@ const notifyHardbounceToApplicant = async ({ application }: { application: Enfor /** * sends email notification to applicant if it's application hardbounced */ -const warnMatchaTeamAboutBouncedEmail = async ({ application }: { application: EnforceDocument }): Promise => { +const warnMatchaTeamAboutBouncedEmail = async ({ application }: { application: IApplication | any }): Promise => { await mailer.sendEmail({ to: config.transactionalEmail, subject: `Votre candidature n'a pas pu être envoyée à ${application.company_name}`, @@ -803,19 +814,21 @@ export interface IApplicationCount { * @returns {Promise} token data */ export const getApplicationByJobCount = async (job_ids: IApplication["job_id"][]): Promise => { - const applicationCountByJob: IApplicationCount[] = await Application.aggregate([ - { - $match: { - job_id: { $in: job_ids }, + const applicationCountByJob = (await getDbCollection("applications") + .aggregate([ + { + $match: { + job_id: { $in: job_ids }, + }, }, - }, - { - $group: { - _id: "$job_id", - count: { $sum: 1 }, + { + $group: { + _id: "$job_id", + count: { $sum: 1 }, + }, }, - }, - ]) + ]) + .toArray()) as IApplicationCount[] return applicationCountByJob } @@ -826,19 +839,21 @@ export const getApplicationByJobCount = async (job_ids: IApplication["job_id"][] * @returns {Promise} token data */ export const getApplicationByCompanyCount = async (sirets: ILbaCompany["siret"][]): Promise => { - const applicationCountByCompany: IApplicationCount[] = await Application.aggregate([ - { - $match: { - company_siret: { $in: sirets }, + const applicationCountByCompany = (await getDbCollection("applications") + .aggregate([ + { + $match: { + company_siret: { $in: sirets }, + }, }, - }, - { - $group: { - _id: "$company_siret", - count: { $sum: 1 }, + { + $group: { + _id: "$company_siret", + count: { $sum: 1 }, + }, }, - }, - ]) + ]) + .toArray()) as IApplicationCount[] return applicationCountByCompany } @@ -869,7 +884,7 @@ export const processApplicationHardbounceEvent = async (payload) => { export const obfuscateLbaCompanyApplications = async (company_siret: string) => { const fakeEmail = "faux_email@faux-domaine-compagnie.com" - await Application.updateMany( + await getDbCollection("applications").updateMany( { job_origin: { $in: [LBA_ITEM_TYPE_OLD.LBA, LBA_ITEM_TYPE.RECRUTEURS_LBA] }, company_siret }, { $set: { to_company_message_id: fakeEmail, company_email: fakeEmail } } ) diff --git a/server/src/services/appointment.service.ts b/server/src/services/appointment.service.ts index d0177ac30d..453c0ccb37 100644 --- a/server/src/services/appointment.service.ts +++ b/server/src/services/appointment.service.ts @@ -1,42 +1,34 @@ import dayjs from "dayjs" -import type { FilterQuery, ObjectId } from "mongoose" +import { Filter, ObjectId } from "mongodb" import { IAppointment, IEligibleTrainingsForAppointment, IEtablissement, IUser } from "shared" +import { mailType } from "shared/constants/appointment" +import { ReferrerObject } from "shared/constants/referers" -import { mailType } from "@/common/model/constants/appointments" -import { ReferrerObject } from "@/common/model/constants/referrers" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" import config from "@/config" -import { Appointment } from "../common/model/index" +import { getDbCollection } from "../common/utils/mongodbUtils" import { createRdvaAppointmentIdPageLink } from "./appLinks.service" import mailer, { sanitizeForEmail } from "./mailer.service" -export type NewAppointment = Pick< - IAppointment, - "applicant_id" | "cfa_recipient_email" | "cfa_formateur_siret" | "applicant_message_to_cfa" | "applicant_reasons" | "appointment_origin" | "cle_ministere_educatif" -> - -const createAppointment = async (params: NewAppointment) => { - const appointment = new Appointment(params) - await appointment.save() - - return appointment.toObject() +const createAppointment = async (params: Omit) => { + const appointment: IAppointment = { ...params, _id: new ObjectId(), created_at: new Date() } + await getDbCollection("appointments").insertOne(appointment) + return appointment } -const findById = async (id: ObjectId | string): Promise => Appointment.findById(id).lean() - -const find = (conditions: FilterQuery) => Appointment.find(conditions) +const findById = async (id: ObjectId | string): Promise => getDbCollection("appointments").findOne({ _id: new ObjectId(id) }) -const findOne = (conditions: FilterQuery) => Appointment.findOne(conditions) +const find = (conditions: Filter) => getDbCollection("appointments").find(conditions) -const findOneAndUpdate = (conditions: FilterQuery, values) => Appointment.findOneAndUpdate(conditions, values, { new: true }) +const findOne = (conditions: Filter) => getDbCollection("appointments").findOne(conditions) -const updateMany = (conditions: FilterQuery, values) => Appointment.updateMany(conditions, values) +const findOneAndUpdate = (conditions: Filter, values) => getDbCollection("appointments").findOneAndUpdate(conditions, values, { returnDocument: "after" }) -const updateAppointment = (id: string, values) => Appointment.findOneAndUpdate({ _id: id }, values, { new: true }) +const updateAppointment = (id: string, values) => getDbCollection("appointments").findOneAndUpdate({ _id: new ObjectId(id) }, values, { returnDocument: "after" }) -export { createAppointment, find, findById, findOne, findOneAndUpdate, updateAppointment, updateMany } +export { createAppointment, find, findById, findOne, findOneAndUpdate, updateAppointment } const getMailData = (candidate: IUser, appointment: IAppointment, eligibleTrainingsForAppointment: IEligibleTrainingsForAppointment, referrerObj: ReferrerObject) => { const mailData = { @@ -150,16 +142,19 @@ export const processAppointmentToApplicantWebhookEvent = async (payload) => { // deuxième condition ci-dessus utile uniquement pour typescript car to_applicant_mails peut être null selon le typage const firstEmailEvent = appointmentCandidatFound.to_applicant_mails[0] - await appointmentCandidatFound.update({ - $push: { - to_applicant_mails: { - campaign: firstEmailEvent.campaign, - status: event, - message_id: firstEmailEvent.message_id, - webhook_status_at: eventDate, + await getDbCollection("appointments").updateOne( + { _id: appointmentCandidatFound._id }, + { + $push: { + to_applicant_mails: { + campaign: firstEmailEvent.campaign, + status: event, + message_id: firstEmailEvent.message_id, + webhook_status_at: eventDate, + }, }, - }, - }) + } + ) return false } return true @@ -173,18 +168,23 @@ export const processAppointmentToCfaWebhookEvent = async (payload) => { // If mail sent from appointment model const appointment = await findOne({ "to_cfa_mails.message_id": messageId }) if (appointment) { - const firstEmailEvent = appointment.to_cfa_mails[0] - - await appointment.update({ - $push: { - to_cfa_mails: { - campaign: firstEmailEvent.campaign, - status: event, - message_id: firstEmailEvent.message_id, - webhook_status_at: eventDate, - }, - }, - }) + if (appointment.to_cfa_mails?.length) { + const firstEmailEvent = appointment.to_cfa_mails[0] + + await getDbCollection("appointments").updateOne( + { _id: appointment._id }, + { + $push: { + to_cfa_mails: { + campaign: firstEmailEvent.campaign, + status: event, + message_id: firstEmailEvent.message_id, + webhook_status_at: eventDate, + }, + }, + } + ) + } return false } diff --git a/server/src/services/catalogue.service.ts b/server/src/services/catalogue.service.ts index 1431fe178a..d7f944efd8 100644 --- a/server/src/services/catalogue.service.ts +++ b/server/src/services/catalogue.service.ts @@ -4,12 +4,13 @@ import axios, { AxiosInstance } from "axios" import Boom from "boom" import { got } from "got" import { sortBy } from "lodash-es" +import { ObjectId } from "mongodb" import { compose } from "oleoduc" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { sentryCaptureException } from "@/common/utils/sentryUtils" import { logger } from "../common/logger" -import { FormationCatalogue, UnsubscribeOF } from "../common/model/index" import { getDistanceInKm } from "../common/utils/geolib" import { fetchStream } from "../common/utils/httpUtils" import { isValidEmail } from "../common/utils/isValidEmail" @@ -110,7 +111,7 @@ const neededFieldsFromCatalogue = { * @param {String} id * @returns {Promise} */ -export const getFormationById = (id: string) => FormationCatalogue.findById(id) +export const getFormationById = (id: string) => getDbCollection("formationcatalogues").findOne({ _id: new ObjectId(id) }) /** * @description Get formations from the formation catalogue collection. @@ -118,7 +119,7 @@ export const getFormationById = (id: string) => FormationCatalogue.findById(id) * @param {Object} select * @returns {Promise} */ -export const getCatalogueFormations = (query: object, select?: object) => FormationCatalogue.find(query, select).lean() +export const getCatalogueFormations = (query: object, select?: object) => getDbCollection("formationcatalogues").find(query, select).toArray() /** * @description Get formations count through the CARIF OREF catalogue API. @@ -197,7 +198,9 @@ export const getNearEtablissementsFromRomes = async ({ rome, origin }: { rome: s ] }) etablissementsRefined = sortBy(etablissementsRefined, "distance_en_km") - const unsubscribedEtablissements = await UnsubscribeOF.find({ catalogue_id: { $in: etablissementsRefined.map((etablissement) => etablissement._id) } }) + const unsubscribedEtablissements = await getDbCollection("unsubscribedofs") + .find({ catalogue_id: { $in: etablissementsRefined.map((etablissement) => etablissement._id) } }) + .toArray() const unsubscribedIds = unsubscribedEtablissements.map((unsubscribeOF) => unsubscribeOF.catalogue_id) etablissementsRefined = etablissementsRefined.filter((etablissement) => !unsubscribedIds.includes(etablissement._id)) return etablissementsRefined @@ -305,7 +308,7 @@ export const getRomesFromCatalogue = async ({ if (cfd) query.cfd = cfd if (siret) query.etablissement_formateur_siret = siret - const formationsFromDb = await FormationCatalogue.find(query).lean() + const formationsFromDb = await getDbCollection("formationcatalogues").find(query) const romes: Set = new Set() diff --git a/server/src/services/cfa.service.ts b/server/src/services/cfa.service.ts index 7965c228e8..7398dfe758 100644 --- a/server/src/services/cfa.service.ts +++ b/server/src/services/cfa.service.ts @@ -1,19 +1,25 @@ +import { ObjectId } from "mongodb" import { ICFA } from "shared/models/cfa.model" -import { Cfa } from "@/common/model" +import { getDbCollection } from "../common/utils/mongodbUtils" export const upsertCfa = async (siret: string, cfaFields: Omit, origin: string): Promise => { - let cfa = await Cfa.findOne({ siret }).lean() + const now = new Date() + let cfa = await getDbCollection("cfas").findOne({ siret }) if (cfa) { - cfa = await Cfa.findOneAndUpdate({ siret }, { $set: { ...cfaFields, siret } }, { new: true }).lean() + cfa = await getDbCollection("cfas").findOneAndUpdate({ siret }, { $set: { ...cfaFields, siret } }, { returnDocument: "after" }) if (!cfa) throw new Error("inattendu: pas de cfa") + return cfa } else { - const createCfaFields: Omit = { + const createCfaFields: ICFA = { ...cfaFields, origin, siret, + _id: new ObjectId(), + createdAt: now, + updatedAt: now, } - cfa = (await Cfa.create(createCfaFields)).toObject() + await getDbCollection("cfas").insertOne(createCfaFields) + return createCfaFields } - return cfa } diff --git a/server/src/services/eligibleTrainingsForAppointment.service.ts b/server/src/services/eligibleTrainingsForAppointment.service.ts index 5ad4fe4053..992f7bae44 100644 --- a/server/src/services/eligibleTrainingsForAppointment.service.ts +++ b/server/src/services/eligibleTrainingsForAppointment.service.ts @@ -1,36 +1,36 @@ import Boom from "boom" -import type { ObjectId } from "mongodb" -import type { FilterQuery } from "mongoose" +import { Filter, ObjectId } from "mongodb" import { IEligibleTrainingsForAppointment, IFormationCatalogue } from "shared" import { IAppointmentRequestContextCreateResponseSchema } from "shared/routes/appointments.routes" import { logger } from "@/common/logger" -import { getReferrerByKeyName } from "@/common/model/constants/referrers" +import { getDbCollection } from "@/common/utils/mongodbUtils" import config from "@/config" -import { EligibleTrainingsForAppointment, Etablissement, ReferentielOnisep } from "../common/model/index" import { isValidEmail } from "../common/utils/isValidEmail" import { isEmailBlacklisted } from "./application.service" import { getMostFrequentEmailByGestionnaireSiret } from "./formation.service" +import { getReferrerByKeyName } from "./referrers.service" -export const create = (params: Partial) => EligibleTrainingsForAppointment.create(params) +export const create = (params: IEligibleTrainingsForAppointment) => getDbCollection("eligible_trainings_for_appointments").insertOne(params) -export const find = (conditions: FilterQuery, options = {}) => EligibleTrainingsForAppointment.find(conditions, options) +export const find = (conditions: Filter, options = {}) => + getDbCollection("eligible_trainings_for_appointments").find(conditions, options).toArray() -export const findOne = (conditions: FilterQuery) => EligibleTrainingsForAppointment.findOne(conditions) +export const findOne = (conditions: Filter, options = {}) => getDbCollection("eligible_trainings_for_appointments").findOne(conditions, options) -export const updateParameter = (id: ObjectId | string, params: Partial) => - EligibleTrainingsForAppointment.findOneAndUpdate({ _id: id }, params, { new: true }) +export const updateParameter = (id: ObjectId, params: Partial) => + getDbCollection("eligible_trainings_for_appointments").findOneAndUpdate({ _id: id }, params, { returnDocument: "after" }) -export const remove = (id: string) => EligibleTrainingsForAppointment.findByIdAndDelete(id) +export const findOneAndUpdate = (conditions: Filter, values) => + getDbCollection("eligible_trainings_for_appointments").findOneAndUpdate(conditions, { $set: values }, { returnDocument: "after", upsert: true }) -export const updateMany = (conditions: FilterQuery, values) => - EligibleTrainingsForAppointment.updateMany(conditions, values, { new: true, upsert: true }) +export const updateMany = (conditions: Filter, values) => + getDbCollection("eligible_trainings_for_appointments").updateMany(conditions, { $set: values }) -export const update = (conditions: FilterQuery, values) => EligibleTrainingsForAppointment.updateMany(conditions, values, { new: true }) - -export const getParameterByCleMinistereEducatif = ({ cleMinistereEducatif }) => EligibleTrainingsForAppointment.findOne({ cle_ministere_educatif: cleMinistereEducatif }).lean() +export const getParameterByCleMinistereEducatif = ({ cleMinistereEducatif }) => + getDbCollection("eligible_trainings_for_appointments").findOne({ cle_ministere_educatif: cleMinistereEducatif }) export const getEmailForRdv = async ( formation: Pick, @@ -50,7 +50,7 @@ export const disableEligibleTraininForAppointmentWithEmail = async (disabledEmai await Promise.all( eligibleTrainingsForAppointmentsWithEmail.map(async (eligibleTrainingsForAppointment) => { - await eligibleTrainingsForAppointment.update({ referrers: [], lieu_formation_email: "" }) + await getDbCollection("eligible_trainings_for_appointments").updateOne({ _id: eligibleTrainingsForAppointment._id }, { $set: { referrers: [], lieu_formation_email: "" } }) logger.info('Eligible training disabled for "hard_bounce" reason', { eligibleTrainingsForAppointmentId: eligibleTrainingsForAppointment._id, @@ -61,21 +61,21 @@ export const disableEligibleTraininForAppointmentWithEmail = async (disabledEmai } const findEligibleTrainingByMinisterialKey = async (idCleMinistereEducatif: string) => { - return await EligibleTrainingsForAppointment.findOne({ cle_ministere_educatif: idCleMinistereEducatif }) + return await getDbCollection("eligible_trainings_for_appointments").findOne({ cle_ministere_educatif: idCleMinistereEducatif }) } const findEligibleTrainingByParcoursupId = async (idParcoursup: string) => { - return await EligibleTrainingsForAppointment.findOne({ parcoursup_id: idParcoursup }) + return await getDbCollection("eligible_trainings_for_appointments").findOne({ parcoursup_id: idParcoursup }) } const findEligibleTrainingByActionFormation = async (idActionFormation: string) => { - const referentielOnisepIdActionFormation = await ReferentielOnisep.findOne({ id_action_ideo2: idActionFormation }) + const referentielOnisepIdActionFormation = await getDbCollection("referentieloniseps").findOne({ id_action_ideo2: idActionFormation }) if (!referentielOnisepIdActionFormation) { throw Boom.notFound("Formation not found") } - return await EligibleTrainingsForAppointment.findOne({ + return await getDbCollection("eligible_trainings_for_appointments").findOne({ cle_ministere_educatif: referentielOnisepIdActionFormation.cle_ministere_educatif, }) } @@ -85,7 +85,7 @@ function isOpenForAppointments(eligibleTrainingsForAppointment: IEligibleTrainin } const findEtablissement = async (formateurSiret: string | null | undefined) => { - return await Etablissement.findOne({ formateur_siret: formateurSiret }) + return await getDbCollection("etablissements").findOne({ formateur_siret: formateurSiret }) } export const findElligibleTrainingForAppointment = async (req: any): Promise => { diff --git a/server/src/services/etablissement.service.ts b/server/src/services/etablissement.service.ts index 2d765ad2a8..5b4d270d64 100644 --- a/server/src/services/etablissement.service.ts +++ b/server/src/services/etablissement.service.ts @@ -2,8 +2,19 @@ import { setTimeout } from "timers/promises" import { AxiosResponse } from "axios" import Boom from "boom" -import type { FilterQuery } from "mongoose" -import { IAdresseV3, IBusinessError, ICfaReferentielData, IEtablissement, ILbaCompany, IRecruiter, IReferentielOpco, ZAdresseV3, ZCfaReferentielData } from "shared" +import { Filter as MongoDBFilter, ObjectId } from "mongodb" +import { + IAdresseV3, + IBusinessError, + ICfaReferentielData, + IEtablissement, + ILbaCompany, + ILbaCompanyLegacy, + IRecruiter, + ISiretDiffusibleStatus, + ZAdresseV3, + ZCfaReferentielData, +} from "shared" import { EDiffusibleStatus } from "shared/constants/diffusibleStatus" import { BusinessErrorCodes } from "shared/constants/errorCodes" import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur" @@ -15,21 +26,10 @@ import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" import { FCGetOpcoInfos } from "@/common/franceCompetencesClient" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" import { getHttpClient } from "@/common/utils/httpUtils" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { userWithAccountToUserForToken } from "@/security/accessTokenService" -import { isUserEmailChecked, emailHasActiveRole } from "@/services/userWithAccount.service" +import { emailHasActiveRole, isUserEmailChecked } from "@/services/userWithAccount.service" -import { - Cfa, - Entreprise, - Etablissement, - LbaCompany, - LbaCompanyLegacy, - ReferentielOpco, - RoleManagement, - SiretDiffusibleStatus, - UnsubscribeOF, - UserWithAccount, -} from "../common/model/index" import { isEmailFromPrivateCompany, isEmailSameDomain } from "../common/utils/mailUtils" import { sentryCaptureException } from "../common/utils/sentryUtils" import config from "../config" @@ -39,16 +39,7 @@ import { validationOrganisation } from "./bal.service" import { getCatalogueEtablissements } from "./catalogue.service" import { CFA, ENTREPRISE, RECRUITER_STATUS } from "./constant.service" import dayjs from "./dayjs.service" -import { - IAPIAdresse, - IAPIEtablissement, - ICFADock, - IEtablissementCatalogue, - IEtablissementGouv, - IFormatAPIEntreprise, - IReferentiel, - ISIRET2IDCC, -} from "./etablissement.service.types" +import { IAPIAdresse, IAPIEtablissement, ICFADock, IEtablissementGouv, IFormatAPIEntreprise, IReferentiel, ISIRET2IDCC } from "./etablissement.service.types" import { createFormulaire, getFormulaire } from "./formulaire.service" import mailer, { sanitizeForEmail } from "./mailer.service" import { getOpcoBySirenFromDB, saveOpco } from "./opco.service" @@ -120,92 +111,19 @@ const getEffectif = (code) => { } } -/** - * @description Creates an etablissement. - * @param {Object} options - * @returns {Promise} - */ -export const create = async (options = {}) => { - const etablissement = new Etablissement(options) - await etablissement.save() - - return etablissement.toObject() -} - -/** - * @description Returns an etablissement from its id. - * @param {ObjectId} id - * @returns {Promise} - */ -export const findById = async (id): Promise => { - const etablissement = await Etablissement.findById(id) - - if (!etablissement) { - throw new Error(`Unable to find etablissement ${id}`) - } - - return etablissement.toObject() -} - -/** - * @description Returns items. - * @param {Object} conditions - * @returns {Promise} - */ -export const find = async (conditions): Promise => Etablissement.find(conditions).lean() - /** * @description Returns one item. * @param {Object} conditions * @returns {Promise} */ -export const findOne = async (conditions): Promise => Etablissement.findOne(conditions).lean() - -/** - * @description Updates an etablissement from its conditions. - * @param {Object} conditions - * @param {Object} values - * @returns {Promise} - */ -export const findOneAndUpdate = async (conditions, values): Promise => Etablissement.findOneAndUpdate(conditions, values, { new: true }).lean() - -/** - * @description Upserts. - * @param {Object} conditions - * @param {Object} values - * @returns {Promise} - */ -export const updateMany = async (conditions, values): Promise => Etablissement.updateMany(conditions, values, { new: true, upsert: true }).lean() - -/** - * @description Update one. - * @param {Object} conditions - * @param {Object} values - * @returns {Promise} - */ -export const updateOne = async (conditions, values): Promise => Etablissement.updateOne(conditions, values, { new: true, upsert: true }).lean() - -/** - * @description Updates an etablissement from its id. - * @param {ObjectId} id - * @param {Object} values - * @returns {Promise} - */ -export const findByIdAndUpdate = async (id, values): Promise => Etablissement.findByIdAndUpdate({ _id: id }, values, { new: true }).lean() - -/** - * @description Deletes an etablissement from its id. - * @param {ObjectId} id - * @returns {Promise} - */ -export const findByIdAndDelete = async (id): Promise => Etablissement.findByIdAndDelete(id).lean() +export const findOne = async (conditions): Promise => getDbCollection("etablissements").findOne(conditions) /** * @description Get opco details from CFADOCK API for a given SIRET * @param {String} siret * @returns {Promise} */ -export const getOpcoFromCfaDock = async (siret: string): Promise<{ opco: string; idcc?: string } | undefined> => { +const getOpcoFromCfaDock = async (siret: string): Promise<{ opco: string; idcc?: string } | undefined> => { try { const { data } = await getHttpClient({ timeout: 5000 }).get(`https://www.cfadock.fr/api/opcos?siret=${encodeURIComponent(siret)}`) if (!data) { @@ -234,7 +152,7 @@ export const getOpcoFromCfaDock = async (siret: string): Promise<{ opco: string; * @param {Number} idcc * @returns {Promise} */ -export const getOpcoByIdcc = async (idcc: number): Promise => { +const getOpcoByIdcc = async (idcc: number): Promise => { try { const { data } = await getHttpClient({ timeout: 5000 }).get(`https://www.cfadock.fr/api/opcos?idcc=${idcc}`) return data @@ -249,7 +167,7 @@ export const getOpcoByIdcc = async (idcc: number): Promise => { * @param {String} siret * @returns {Promise} */ -export const getIdcc = async (siret: string): Promise => { +const getIdcc = async (siret: string): Promise => { try { const { data } = await getHttpClient({ timeout: 5000 }).get(`https://siret2idcc.fabrique.social.gouv.fr/api/v2/${encodeURIComponent(siret)}`) return data @@ -262,7 +180,7 @@ export const getIdcc = async (siret: string): Promise => { /** * @description Get the establishment information from the ENTREPRISE API for a given SIRET */ -export const getEtablissementFromGouvSafe = async (siret: string): Promise => { +const getEtablissementFromGouvSafe = async (siret: string): Promise => { try { if (config.entreprise.simulateError) { throw new Error("API entreprise : simulation d'erreur") @@ -291,13 +209,13 @@ export const getEtablissementFromGouvSafe = async (siret: string): Promise => { +const getEtablissementDiffusionStatus = async (siret: string): Promise => { try { if (config.entreprise.simulateError) { throw new Error("API entreprise : simulation d'erreur") } - const siretDiffusibleStatus = await SiretDiffusibleStatus.findOne({ siret }).lean() + const siretDiffusibleStatus = await getDbCollection("siretdiffusiblestatuses").findOne({ siret }) if (siretDiffusibleStatus) { return siretDiffusibleStatus.status_diffusion } @@ -331,12 +249,17 @@ export const getEtablissementDiffusionStatus = async (siret: string): Promise { +const saveSiretDiffusionStatus = async (siret, diffusionStatus) => { try { - await new SiretDiffusibleStatus({ + const now = new Date() + const obj: ISiretDiffusibleStatus = { + _id: new ObjectId(), siret, status_diffusion: diffusionStatus, - }).save() + created_at: now, + last_update_at: now, + } + await getDbCollection("siretdiffusiblestatuses").insertOne(obj) } catch (err) { // non blocking error sentryCaptureException(err) @@ -372,7 +295,7 @@ export const getEtablissementFromGouv = async (siret: string): Promise => { +const getEtablissementFromReferentiel = async (siret: string): Promise => { try { const { data } = await getHttpClient().get(`https://referentiel.apprentissage.beta.gouv.fr/api/v1/organismes/${siret}`) return data @@ -385,24 +308,6 @@ export const getEtablissementFromReferentiel = async (siret: string): Promise} - */ -export const getEtablissementFromCatalogue = async (siret: string): Promise => { - try { - const result: IEtablissementCatalogue = await getHttpClient().get("https://catalogue.apprentissage.beta.gouv.fr/api/v1/entity/etablissements/", { - params: { - query: { siret }, - }, - }) - return result - } catch (error: any) { - sentryCaptureException(error) - return error - } -} // when in string format: $latitude,$longitude export type GeoCoord = { @@ -435,32 +340,13 @@ export const getGeoCoordinates = async (adresse: string): Promise => { } } -/** - * @description Get matching records from the ReferentielOpco collection for a given siret & email - * @param {IReferentielOpco["siret_code"]} siretCode - * @returns {Promise} - */ -export const getEstablishmentFromOpcoReferentiel = async (siretCode: IReferentielOpco["siret_code"]) => await ReferentielOpco.findOne({ siret_code: siretCode }) -/** - * @description Get all matching records from the ReferentielOpco collection - * @param {FilterQuery} query - * @returns {Promise} - */ -export const getAllEstablishmentFromOpcoReferentiel = async (query: FilterQuery): Promise => await ReferentielOpco.find(query).lean() -/** - * @description Get all matching records from the LbaCompanyLegacy collection - * @param {FilterQuery} query - * @returns {Promise} - */ -export const getAllEstablishmentFromLbaCompanyLegacy = async (query: FilterQuery): Promise => - await LbaCompanyLegacy.find(query).select({ email: 1, _id: 0 }).lean() +type IGetAllEmailFromLbaCompanyLegacy = Pick +export const getAllEstablishmentFromLbaCompanyLegacy = async (query: MongoDBFilter) => + (await getDbCollection("bonnesboiteslegacies").find(query).project({ email: 1, _id: 0 }).toArray()) as IGetAllEmailFromLbaCompanyLegacy[] -/** - * @description Get all matching records from the LbaCompanies collection - * @param {FilterQuery} query - * @returns {Promise} - */ -export const getAllEstablishmentFromLbaCompany = async (query: FilterQuery): Promise => await LbaCompany.find(query).select({ email: 1, _id: 0 }).lean() +type IGetAllEmailFromLbaCompany = Pick +export const getAllEstablishmentFromLbaCompany = async (query: MongoDBFilter) => + (await getDbCollection("bonnesboites").find(query).project({ email: 1, _id: 0 }).toArray()) as IGetAllEmailFromLbaCompany[] function getRaisonSocialeFromGouvResponse(d: IEtablissementGouv): string | undefined { const { personne_morale_attributs, personne_physique_attributs } = d.unite_legale @@ -482,7 +368,7 @@ const addressDetailToString = (address: IAdresseV3): string => { /** * @description Format Entreprise data */ -export const formatEntrepriseData = (d: IEtablissementGouv): IFormatAPIEntreprise => { +const formatEntrepriseData = (d: IEtablissementGouv): IFormatAPIEntreprise => { if (!d.adresse) { throw new Error("erreur dans le format de l'api SIRENE : le champ adresse est vide") } @@ -548,7 +434,7 @@ export const formatReferentielData = (d: IReferentiel): ICfaReferentielData => { * @param etablissementSiret siret de l'organisme de formation ne souhaitant plus recevoir les demandes */ export const etablissementUnsubscribeDemandeDelegation = async (etablissementSiret: string) => { - const unsubscribeOF = await UnsubscribeOF.findOne({ establishment_siret: etablissementSiret }) + const unsubscribeOF = await getDbCollection("unsubscribedofs").findOne({ establishment_siret: etablissementSiret }) if (!unsubscribeOF) { const { etablissements } = await getCatalogueEtablissements( @@ -559,7 +445,8 @@ export const etablissementUnsubscribeDemandeDelegation = async (etablissementSir ) const [{ _id }] = etablissements if (!_id) return - await UnsubscribeOF.create({ + await getDbCollection("unsubscribedofs").insertOne({ + _id: new ObjectId(), catalogue_id: _id, establishment_siret: etablissementSiret, unsubscribe_date: new Date(), @@ -578,7 +465,7 @@ export const autoValidateUserRoleOnCompany = async (userAndEntreprise: UserAndOr return { validated } } -export const isCompanyValid = async (props: UserAndOrganization): Promise<{ isValid: boolean; validator: string }> => { +const isCompanyValid = async (props: UserAndOrganization): Promise<{ isValid: boolean; validator: string }> => { const { organization, user: { email }, @@ -594,7 +481,9 @@ export const isCompanyValid = async (props: UserAndOrganization): Promise<{ isVa const [bonneBoiteLegacyList, bonneBoiteList, referentielOpcoList] = await Promise.all([ getAllEstablishmentFromLbaCompanyLegacy({ siret: { $regex: sirenRegex }, email: { $nin: ["", null] } }), getAllEstablishmentFromLbaCompany({ siret: { $regex: sirenRegex }, email: { $nin: ["", null] } }), - getAllEstablishmentFromOpcoReferentiel({ siret_code: { $regex: sirenRegex } }), + getDbCollection("referentielopcos") + .find({ siret_code: { $regex: sirenRegex } }) + .toArray(), ]) // Format arrays to get only the emails @@ -645,7 +534,7 @@ export const getOpcoData = async (siret: string): Promise<{ opco: string; idcc?: if (opcoFromDB) { return opcoFromDB } - const entreprise = await Entreprise.findOne({ siret }).lean() + const entreprise = await getDbCollection("entreprises").findOne({ siret }) if (entreprise) { const { opco, idcc } = entreprise if (opco) { @@ -710,9 +599,9 @@ export const getEntrepriseDataFromSiret = async ({ siret, type }: { siret: strin } export const isCfaCreationValid = async (siret: string): Promise => { - const cfa = await Cfa.findOne({ siret }).lean() + const cfa = await getDbCollection("cfas").findOne({ siret }) if (!cfa) return true - const roles = await RoleManagement.find({ authorized_type: AccessEntityType.CFA, authorized_id: cfa._id.toString() }).lean() + const roles = await getDbCollection("rolemanagements").find({ authorized_type: AccessEntityType.CFA, authorized_id: cfa._id.toString() }).toArray() const managingAccess = [AccessStatus.GRANTED, AccessStatus.AWAITING_VALIDATION] const managingRoles = roles.filter((role) => { const roleStatus = getLastStatusEvent(role.status)?.status @@ -982,7 +871,7 @@ export const sendEmailConfirmationEntreprise = async ( }, }) } else { - const user2 = await UserWithAccount.findOne({ _id: user._id.toString() }).lean() + const user2 = await getDbCollection("userswithaccounts").findOne({ _id: user._id }) if (!user2) { throw Boom.internal(`could not find user with id=${user._id}`) } diff --git a/server/src/services/formation.service.ts b/server/src/services/formation.service.ts index 41f54b9e38..e0b953ac29 100644 --- a/server/src/services/formation.service.ts +++ b/server/src/services/formation.service.ts @@ -4,7 +4,8 @@ import { chain } from "lodash-es" import { assertUnreachable, type IFormationCatalogue, type ILbaItemFormation2 } from "shared" import { LBA_ITEM_TYPE, LBA_ITEM_TYPE_OLD } from "shared/constants/lbaitem" -import { FormationCatalogue } from "../common/model/index" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import { IApiError } from "../common/utils/errorManager" import { roundDistance } from "../common/utils/geolib" import { isValidEmail } from "../common/utils/isValidEmail" @@ -135,7 +136,7 @@ const getFormations = async ({ query, }, }) - formations = await FormationCatalogue.aggregate(stages) + formations = await getDbCollection("formationcatalogues").aggregate(stages).toArray() } else { stages.unshift({ $match: query, @@ -146,7 +147,7 @@ const getFormations = async ({ }, }) - formations = await FormationCatalogue.aggregate(stages) + formations = await getDbCollection("formationcatalogues").aggregate(stages).toArray() } return formations @@ -226,7 +227,7 @@ const getRegionFormations = async ({ }, }) - const formations: any[] = await FormationCatalogue.aggregate(stages) + const formations: any[] = await getDbCollection("formationcatalogues").aggregate(stages).toArray() if (formations.length === 0 && !caller) { await notifyToSlack({ subject: "FORMATION", message: `Aucune formation par région trouvée pour les romes ${romes} ou le domaine ${romeDomain}.` }) } @@ -756,7 +757,7 @@ export const getFormationsV2 = async ({ * Retourne une formation identifiée par son id */ export const getFormationQuery = async ({ id }: { id: string }): Promise<{ results: ILbaItemFormation[] }> => { - const formation = await FormationCatalogue.findOne({ cle_ministere_educatif: id }).lean() + const formation = await getDbCollection("formationcatalogues").findOne({ cle_ministere_educatif: id }) const formations = formation ? [transformFormation(formation)] : [] return { results: formations } } @@ -765,7 +766,7 @@ export const getFormationQuery = async ({ id }: { id: string }): Promise<{ resul * Retourne une formation identifiée par son id */ export const getFormationv2 = async ({ id }: { id: string }): Promise => { - const formation = await FormationCatalogue.findOne({ cle_ministere_educatif: id }).lean() + const formation = await getDbCollection("formationcatalogues").findOne({ cle_ministere_educatif: id }) if (!formation) { return null } @@ -919,21 +920,25 @@ export const getMostFrequentEmailByGestionnaireSiret = async ( let formations if (type === "email") { - formations = await FormationCatalogue.find( - { - email: { $ne: null }, - etablissement_gestionnaire_siret, - }, - { email: 1 } - ).lean() + formations = await getDbCollection("formationcatalogues") + .find( + { + email: { $ne: null }, + etablissement_gestionnaire_siret, + }, + { projection: { email: 1 } } + ) + .toArray() } else { - formations = await FormationCatalogue.find( - { - etablissement_gestionnaire_courriel: { $ne: null }, - etablissement_gestionnaire_siret, - }, - { etablissement_gestionnaire_courriel: 1 } - ).lean() + formations = await getDbCollection("formationcatalogues") + .find( + { + etablissement_gestionnaire_courriel: { $ne: null }, + etablissement_gestionnaire_siret, + }, + { projection: { etablissement_gestionnaire_courriel: 1 } } + ) + .toArray() } const mostFrequentEmail = chain(formations) diff --git a/server/src/services/formulaire.service.ts b/server/src/services/formulaire.service.ts index 56264739a1..6a60a68cfe 100644 --- a/server/src/services/formulaire.service.ts +++ b/server/src/services/formulaire.service.ts @@ -1,7 +1,7 @@ +import { randomUUID } from "node:crypto" + import Boom from "boom" -import type { ObjectId as ObjectIdType } from "mongodb" -import pkg from "mongodb" -import type { FilterQuery, ModelUpdateOptions, UpdateQuery } from "mongoose" +import { Filter, ObjectId, UpdateFilter } from "mongodb" import { IDelegation, IJob, IJobWithRomeDetail, IJobWritable, IRecruiter, IUserRecruteur, JOB_STATUS } from "shared" import { RECRUITER_STATUS } from "shared/constants/recruteur" import { EntrepriseStatus, IEntreprise } from "shared/models/entreprise.model" @@ -11,8 +11,8 @@ import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" -import { Cfa, Entreprise, Recruiter, RoleManagement, UnsubscribeOF } from "../common/model/index" import { asyncForEach } from "../common/utils/asyncUtils" +import { getDbCollection } from "../common/utils/mongodbUtils" import config from "../config" import { getUser2ManagingOffer } from "./application.service" @@ -24,8 +24,6 @@ import mailer, { sanitizeForEmail } from "./mailer.service" import { getComputedUserAccess, getGrantedRoles } from "./roleManagement.service" import { getRomeDetailsFromDB } from "./rome.service" -const { ObjectId } = pkg - export interface IOffreExtended extends IJob { candidatures: number pourvue: string @@ -71,7 +69,7 @@ export const romeDetailAggregateStages = [ /** * @description get formulaire by offer id */ -export const getOffreAvecInfoMandataire = async (id: string | ObjectIdType): Promise<{ recruiter: IRecruiter; job: IJob } | null> => { +export const getOffreAvecInfoMandataire = async (id: string | ObjectId): Promise<{ recruiter: IRecruiter; job: IJob } | null> => { const recruiterOpt = await getOffreWithRomeDetail(id) if (!recruiterOpt) { @@ -85,7 +83,7 @@ export const getOffreAvecInfoMandataire = async (id: string | ObjectIdType): Pro if (recruiterOpt.is_delegated && recruiterOpt.address) { const { cfa_delegated_siret } = recruiterOpt if (cfa_delegated_siret) { - const cfa = await Cfa.findOne({ siret: cfa_delegated_siret }).lean() + const cfa = await getDbCollection("cfas").findOne({ siret: cfa_delegated_siret }) if (cfa) { const cfaUser = await getUser2ManagingOffer(getJobFromRecruiter(recruiterOpt, id.toString())) @@ -105,26 +103,28 @@ export const getOffreAvecInfoMandataire = async (id: string | ObjectIdType): Pro /** * @description Get formulaire list with mondodb paginate query * @param {Object} payload - * @param {FilterQuery} payload.query + * @param {Filter} payload.query * @param {object} payload.options * @param {number} payload.page * @param {number} payload.limit */ -export const getFormulaires = async (query: FilterQuery, select: object, { page, limit }: { page?: number; limit?: number }) => { - const response = await Recruiter.paginate({ query, select, page, limit, lean: true }) - +export const getFormulaires = async (query: Filter, select: object, { page, limit }: { page?: number; limit?: number }) => { + const response = getDbCollection("recruiters").find({ query }, { projection: select }) + const data = page && limit ? await response.skip(page).limit(limit).toArray() : await response.toArray() + const total = await getDbCollection("recruiters").countDocuments(query) + const number_of_page = limit ? Math.ceil(total / limit) : undefined return { pagination: { - page: response?.page, + page, result_per_page: limit, - number_of_page: response?.totalPages, - total: response?.totalDocs, + number_of_page, + total, }, - data: response?.docs, + data, } } -const isAuthorizedToPublishJob = async ({ userId, entrepriseId }: { userId: ObjectIdType; entrepriseId: ObjectIdType }) => { +const isAuthorizedToPublishJob = async ({ userId, entrepriseId }: { userId: ObjectId; entrepriseId: ObjectId }) => { const access = getComputedUserAccess(userId.toString(), await getGrantedRoles(userId.toString())) return access.admin || access.entreprises.includes(entrepriseId.toString()) } @@ -134,12 +134,14 @@ const isAuthorizedToPublishJob = async ({ userId, entrepriseId }: { userId: Obje */ export const createJob = async ({ job, establishment_id, user }: { job: IJobWritable; establishment_id: string; user: IUserWithAccount }): Promise => { const userId = user._id - const recruiter = await Recruiter.findOne({ establishment_id: establishment_id }).lean() + const recruiter = await getDbCollection("recruiters").findOne({ establishment_id: establishment_id }) if (!recruiter) { throw Boom.internal(`recruiter with establishment_id=${establishment_id} not found`) } const { is_delegated, cfa_delegated_siret } = recruiter - const organization = await (cfa_delegated_siret ? Cfa.findOne({ siret: cfa_delegated_siret }).lean() : Entreprise.findOne({ siret: recruiter.establishment_siret }).lean()) + const organization = await (cfa_delegated_siret + ? getDbCollection("cfas").findOne({ siret: cfa_delegated_siret }) + : getDbCollection("entreprises").findOne({ siret: recruiter.establishment_siret })) if (!organization) { throw Boom.internal(`inattendu : impossible retrouver l'organisation pour establishment_id=${establishment_id}`) } @@ -171,7 +173,7 @@ export const createJob = async ({ job, establishment_id, user }: { job: IJobWrit job_creation_date: creationDate, job_expiration_date: addExpirationPeriod(creationDate).toDate(), job_update_date: creationDate, - managed_by: userId, + managed_by: userId.toString(), }) // insert job const updatedFormulaire = await createOffre(establishment_id, updatedJob) @@ -185,7 +187,7 @@ export const createJob = async ({ job, establishment_id, user }: { job: IJobWrit if (!entrepriseStatus) { throw Boom.internal(`inattendu : pas de status pour l'entreprise pour establishment_id=${establishment_id}`) } - const role = await RoleManagement.findOne({ user_id: userId, authorized_type: AccessEntityType.ENTREPRISE, authorized_id: organization._id.toString() }).lean() + const role = await getDbCollection("rolemanagements").findOne({ user_id: userId, authorized_type: AccessEntityType.ENTREPRISE, authorized_id: organization._id.toString() }) const roleStatus = getLastStatusEvent(role?.status)?.status ?? null await sendEmailConfirmationEntreprise(user, updatedFormulaire, roleStatus, entrepriseStatus) return updatedFormulaire @@ -216,10 +218,14 @@ export const createJobDelegations = async ({ jobId, etablissementCatalogueIds }: } const offre = getJobFromRecruiter(recruiter, jobId.toString()) const managingUser = await getUser2ManagingOffer(offre) - const entreprise = await Entreprise.findOne({ siret: recruiter.establishment_siret }).lean() + const entreprise = await getDbCollection("entreprises").findOne({ siret: recruiter.establishment_siret }) let shouldSentMailToCfa = false if (entreprise) { - const role = await RoleManagement.findOne({ user_id: managingUser._id, authorized_id: entreprise._id.toString(), authorized_type: AccessEntityType.ENTREPRISE }).lean() + const role = await getDbCollection("rolemanagements").findOne({ + user_id: managingUser._id, + authorized_id: entreprise._id.toString(), + authorized_type: AccessEntityType.ENTREPRISE, + }) if (role && getLastStatusEvent(role.status)?.status === AccessStatus.GRANTED) { shouldSentMailToCfa = true } @@ -271,24 +277,26 @@ export const createJobDelegations = async ({ jobId, etablissementCatalogueIds }: * @returns {Promise} */ export const checkOffreExists = async (id: IJob["_id"]): Promise => { - const offre = await getOffre(id.toString()) + const offre = await getOffre(id) return offre ? true : false } /** * @description Find formulaire by query - * @param {FilterQuery} query + * @param {Filter} query * @returns {Promise} */ -export const getFormulaire = async (query: FilterQuery): Promise => Recruiter.findOne(query).lean() +export const getFormulaire = async (query: Filter): Promise => getDbCollection("recruiters").findOne(query) -export const getFormulaireWithRomeDetail = async (query: FilterQuery): Promise => { - const recruiterWithRomeDetail: IRecruiter[] = await Recruiter.aggregate([ - { - $match: query, - }, - ...romeDetailAggregateStages, - ]) +export const getFormulaireWithRomeDetail = async (query: Filter): Promise => { + const recruiterWithRomeDetail: IRecruiter[] = (await getDbCollection("recruiters") + .aggregate([ + { + $match: query, + }, + ...romeDetailAggregateStages, + ]) + .toArray()) as IRecruiter[] return recruiterWithRomeDetail.length ? recruiterWithRomeDetail[0] : await getFormulaire(query) } @@ -299,14 +307,27 @@ export const getFormulaireWithRomeDetail = async (query: FilterQuery * @returns {Promise} */ export const createFormulaire = async (payload: Partial>, managedBy: string): Promise => { - const recruiter = await Recruiter.create({ ...payload, managed_by: managedBy }) - return recruiter.toObject() + const recruiter: IRecruiter = { + ...payload, + managed_by: managedBy, + _id: new ObjectId(), + createdAt: new Date(), + updatedAt: new Date(), + establishment_id: randomUUID(), + status: RECRUITER_STATUS.ACTIF, + email: payload.email as string, + establishment_siret: payload.establishment_siret as string, + is_delegated: payload.is_delegated ?? (false as boolean), + jobs: [], + } + await getDbCollection("recruiters").insertOne(recruiter) + return recruiter } /** * Remove formulaire by id */ -export const deleteFormulaire = async (id: IRecruiter["_id"]): Promise => await Recruiter.findByIdAndDelete(id) +export const deleteFormulaire = async (id: IRecruiter["_id"]): Promise => await getDbCollection("recruiters").findOneAndDelete({ _id: id }) /** * @description Remove all formulaires belonging to gestionnaire @@ -314,14 +335,14 @@ export const deleteFormulaire = async (id: IRecruiter["_id"]): Promise} */ export const deleteFormulaireFromGestionnaire = async (siret: IUserRecruteur["establishment_siret"]): Promise => { - await Recruiter.deleteMany({ cfa_delegated_siret: siret }) + await getDbCollection("recruiters").deleteMany({ cfa_delegated_siret: siret }) } /** * @description Update existing formulaire and return updated version */ -export const updateFormulaire = async (establishment_id: IRecruiter["establishment_id"], payload: UpdateQuery): Promise => { - const recruiter = await Recruiter.findOneAndUpdate({ establishment_id }, payload, { new: true }).lean() +export const updateFormulaire = async (establishment_id: IRecruiter["establishment_id"], payload: UpdateFilter): Promise => { + const recruiter = await getDbCollection("recruiters").findOneAndUpdate({ establishment_id }, { $set: { ...payload, updatedAt: new Date() } }, { returnDocument: "after" }) if (!recruiter) { throw Boom.internal("Recruiter not found") } @@ -334,7 +355,7 @@ export const updateFormulaire = async (establishment_id: IRecruiter["establishme * @returns {Promise} */ export const archiveFormulaire = async (id: IRecruiter["establishment_id"]): Promise => { - const recruiter = await Recruiter.findOne({ establishment_id: id }) + const recruiter = await getDbCollection("recruiters").findOne({ establishment_id: id }) if (!recruiter) { throw Boom.internal("Recruiter not found") } @@ -345,7 +366,7 @@ export const archiveFormulaire = async (id: IRecruiter["establishment_id"]): Pro job.job_status = JOB_STATUS.ANNULEE }) - await recruiter.save() + await getDbCollection("recruiters").findOneAndUpdate({ _id: recruiter._id }, { $set: { ...recruiter, updatedAt: new Date() } }) return true } @@ -356,12 +377,11 @@ export const archiveFormulaire = async (id: IRecruiter["establishment_id"]): Pro * @returns {Promise} */ export const reactivateRecruiter = async (id: IRecruiter["_id"]): Promise => { - const recruiter = await Recruiter.findOne({ _id: id }) + const recruiter = await getDbCollection("recruiters").findOne({ _id: id }) if (!recruiter) { throw Boom.internal("Recruiter not found") } - recruiter.status = RECRUITER_STATUS.ACTIF - await recruiter.save() + await getDbCollection("recruiters").updateOne({ _id: id }, { $set: { status: RECRUITER_STATUS.ACTIF, updatedAt: new Date() } }) return true } @@ -371,7 +391,7 @@ export const reactivateRecruiter = async (id: IRecruiter["_id"]): Promise} */ export const archiveDelegatedFormulaire = async (siret: IUserRecruteur["establishment_siret"]): Promise => { - const formulaires = await Recruiter.find({ cfa_delegated_siret: siret }).lean() + const formulaires = await getDbCollection("recruiters").find({ cfa_delegated_siret: siret }).toArray() if (!formulaires.length) return false @@ -382,7 +402,7 @@ export const archiveDelegatedFormulaire = async (siret: IUserRecruteur["establis job.job_status = JOB_STATUS.ANNULEE }) - await Recruiter.findByIdAndUpdate(form._id, form) + await getDbCollection("recruiters").findOneAndUpdate(form._id, { $set: { ...form, updatedAt: new Date() } }) }) return true @@ -392,17 +412,20 @@ export const archiveDelegatedFormulaire = async (siret: IUserRecruteur["establis * @description Get job offer by job id * @param {IJob["_id"]} id */ -export async function getOffre(id: string | ObjectIdType) { - return Recruiter.findOne({ "jobs._id": id }).lean() +export async function getOffre(id: string | ObjectId) { + return getDbCollection("recruiters").findOne({ "jobs._id": new ObjectId(id.toString()) }) } -export async function getOffreWithRomeDetail(id: string | ObjectIdType) { - const recruiter: IRecruiter[] = await Recruiter.aggregate([ - { - $match: { "jobs._id": new ObjectId(id) }, - }, - ...romeDetailAggregateStages, - ]) +export async function getOffreWithRomeDetail(id: string | ObjectId) { + // return a Document type incompatible, to be checked + const recruiter = (await getDbCollection("recruiters") + .aggregate([ + { + $match: { "jobs._id": new ObjectId(id) }, + }, + ...romeDetailAggregateStages, + ]) + .toArray()) as IRecruiter[] return recruiter.length ? recruiter[0] : null } @@ -410,8 +433,13 @@ export async function getOffreWithRomeDetail(id: string | ObjectIdType) { /** * Create job offer on existing formulaire */ -export async function createOffre(establishment_id: IRecruiter["establishment_id"], payload: UpdateQuery): Promise { - const recruiter = await Recruiter.findOneAndUpdate({ establishment_id }, { $push: { jobs: payload } }, { new: true }).lean() +export async function createOffre(establishment_id: IRecruiter["establishment_id"], payload: UpdateFilter): Promise { + const recruiter = await getDbCollection("recruiters").findOneAndUpdate( + { establishment_id }, + // @ts-ignore TODO: fix + { $push: { jobs: { ...payload, _id: new ObjectId() } } }, // jobs timestamp are delivered in payload + { returnDocument: "after" } + ) if (!recruiter) { throw Boom.internal("Recruiter not found") @@ -426,16 +454,16 @@ export async function createOffre(establishment_id: IRecruiter["establishment_id * @param {object} payload * @returns {Promise} */ -export async function updateOffre(id: string | ObjectIdType, payload: UpdateQuery): Promise { - const recruiter = await Recruiter.findOneAndUpdate( +export async function updateOffre(id: string | ObjectId, payload: UpdateFilter): Promise { + const recruiter = await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { $set: { "jobs.$": payload, }, }, - { new: true } - ).lean() + { returnDocument: "after" } + ) if (!recruiter) { throw Boom.internal("Recruiter not found") } @@ -448,19 +476,19 @@ export async function updateOffre(id: string | ObjectIdType, payload: UpdateQuer * @param {object} payload * @returns {Promise} */ -export const patchOffre = async (id: IJob["_id"], payload: UpdateQuery, options: ModelUpdateOptions = { new: true }): Promise => { +export const patchOffre = async (id: IJob["_id"], payload: UpdateFilter): Promise => { const fields = {} for (const key in payload) { fields[`jobs.$.${key}`] = payload[key] } - const recruiter = await Recruiter.findOneAndUpdate( + const recruiter = await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { - $set: fields, + $set: { ...fields, "jobs.$.job_update_date": new Date(), updatedAt: new Date() }, }, - options - ).lean() + { returnDocument: "after" } + ) if (!recruiter) { throw Boom.internal("Recruiter not found") @@ -475,12 +503,12 @@ export const patchOffre = async (id: IJob["_id"], payload: UpdateQuery, op * @returns {Promise} */ export const provideOffre = async (id: IJob["_id"]): Promise => { - await Recruiter.findOneAndUpdate( + await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { $set: { "jobs.$.job_status": JOB_STATUS.POURVUE, - "jobs.$.job_update_date": Date.now(), + "jobs.$.job_update_date": new Date(), }, } ) @@ -493,12 +521,12 @@ export const provideOffre = async (id: IJob["_id"]): Promise => { * @returns {Promise} */ export const cancelOffre = async (id: IJob["_id"]): Promise => { - await Recruiter.findOneAndUpdate( + await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { $set: { "jobs.$.job_status": JOB_STATUS.ANNULEE, - "jobs.$.job_update_date": Date.now(), + "jobs.$.job_update_date": new Date(), }, } ) @@ -511,15 +539,16 @@ export const cancelOffre = async (id: IJob["_id"]): Promise => { * @returns {Promise} */ export const cancelOffreFromAdminInterface = async (id: IJob["_id"], { job_status, job_status_comment }): Promise => { - await Recruiter.findOneAndUpdate( + await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { $set: { - "jobs.$.job_status": job_status, - "jobs.$.job_status_comment": job_status_comment, - "jobs.$.job_update_date": Date.now(), + "jobs.$[elem].job_status": job_status, + "jobs.$[elem].job_status_comment": job_status_comment, + "jobs.$[elem].job_update_date": new Date(), }, - } + }, + { arrayFilters: [{ "elem._id": id }] } ) return true } @@ -530,18 +559,19 @@ export const cancelOffreFromAdminInterface = async (id: IJob["_id"], { job_statu * @returns {Promise} */ export const extendOffre = async (id: IJob["_id"]): Promise => { - const recruiter = await Recruiter.findOneAndUpdate( + const now = new Date() + const recruiter = await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { $set: { "jobs.$.job_expiration_date": addExpirationPeriod(dayjs()).toDate(), - "jobs.$.job_last_prolongation_date": Date.now(), - "jobs.$.job_update_date": Date.now(), + "jobs.$.job_last_prolongation_date": now, + "jobs.$.job_update_date": now, }, $inc: { "jobs.$.job_prolongation_count": 1 }, }, - { new: true } - ).lean() + { returnDocument: "after" } + ) if (!recruiter) { throw Boom.notFound(`job with id=${id} not found`) } @@ -553,16 +583,17 @@ export const extendOffre = async (id: IJob["_id"]): Promise => { } const activateAndExtendOffre = async (id: IJob["_id"]): Promise => { - const recruiter = await Recruiter.findOneAndUpdate( + const recruiter = await getDbCollection("recruiters").findOneAndUpdate( { "jobs._id": id }, { $set: { - "jobs.$.job_expiration_date": addExpirationPeriod(dayjs()).toDate(), - "jobs.$.job_status": JOB_STATUS.ACTIVE, + "jobs.$[x].job_expiration_date": addExpirationPeriod(dayjs()).toDate(), + "jobs.$[x].job_status": JOB_STATUS.ACTIVE, }, }, - { new: true } - ).lean() + { arrayFilters: [{ "x._id": id }], returnDocument: "after" } + ) + console.log({ recruiter }) if (!recruiter) { throw Boom.notFound(`job with id=${id} not found`) } @@ -579,8 +610,10 @@ const activateAndExtendOffre = async (id: IJob["_id"]): Promise => { */ export const activateEntrepriseRecruiterForTheFirstTime = async (entrepriseRecruiter: IRecruiter) => { const firstJob = entrepriseRecruiter.jobs.at(0) + console.log({ firstJob }) if (firstJob) { const job = await activateAndExtendOffre(firstJob._id) + console.log({ job }) // Send delegation if any if (job.delegations?.length) { await Promise.all( @@ -595,7 +628,7 @@ export const activateEntrepriseRecruiterForTheFirstTime = async (entrepriseRecru /** * @description Get job offer by its id. */ -export const getJob = async (id: string | ObjectIdType): Promise => { +export const getJob = async (id: string | ObjectId): Promise => { const offre = await getOffre(id) if (!offre) return null return offre.jobs.find((job) => job._id.toString() === id.toString()) ?? null @@ -604,7 +637,7 @@ export const getJob = async (id: string | ObjectIdType): Promise => /** * @description Get job offer by its id. */ -export const getJobWithRomeDetail = async (id: string | ObjectIdType): Promise => { +export const getJobWithRomeDetail = async (id: string | ObjectId): Promise => { const offre = await getOffre(id) if (!offre) return null @@ -625,7 +658,7 @@ export const getJobWithRomeDetail = async (id: string | ObjectIdType): Promise { - return Recruiter.findOne({ managed_by: userId }).lean() + return getDbCollection("recruiters").findOne({ managed_by: userId }) } export const getFormulaireFromUserIdOrError = async (userId: string) => { diff --git a/server/src/services/lbacompany.service.ts b/server/src/services/lbacompany.service.ts index da112bfaff..720bbf57fc 100644 --- a/server/src/services/lbacompany.service.ts +++ b/server/src/services/lbacompany.service.ts @@ -1,15 +1,13 @@ import Boom from "boom" -import { ILbaCompany, ILbaCompanyForContactUpdate, ERecruteurLbaUpdateEventType } from "shared" -import type { IRecruteurLbaUpdateEventNew } from "shared" +import { ObjectId } from "mongodb" +import { ERecruteurLbaUpdateEventType, ILbaCompany, ILbaCompanyForContactUpdate, IRecruteurLbaUpdateEvent } from "shared" import { LBA_ITEM_TYPE_OLD } from "shared/constants/lbaitem" -import { db } from "@/common/mongodb" - -import { LbaCompany, RecruteurLbaUpdateEvent } from "../common/model/index" import { encryptMailWithIV } from "../common/utils/encryptString" import { IApiError, manageApiError } from "../common/utils/errorManager" import { roundDistance } from "../common/utils/geolib" import { isAllowedSource } from "../common/utils/isAllowedSource" +import { getDbCollection } from "../common/utils/mongodbUtils" import { trackApiCall } from "../common/utils/sendTrackingEvent" import { sentryCaptureException } from "../common/utils/sentryUtils" @@ -204,31 +202,35 @@ const getCompanies = async ({ let companies: ILbaCompany[] = [] - if (latitude) { - companies = await LbaCompany.aggregate([ - { - $geoNear: { - near: { type: "Point", coordinates: [longitude, latitude] }, - distanceField: "distance", - maxDistance: distance * 1000, - query, + if (latitude && longitude) { + companies = (await getDbCollection("bonnesboites") + .aggregate([ + { + $geoNear: { + near: { type: "Point", coordinates: [longitude, latitude] }, + distanceField: "distance", + maxDistance: distance * 1000, + query, + }, + }, + { + $limit: companyLimit, }, - }, - { - $limit: companyLimit, - }, - ]) + ]) + .toArray()) as ILbaCompany[] } else { - companies = await LbaCompany.aggregate([ - { - $match: query, - }, - { - $sample: { - size: companyLimit, + companies = (await getDbCollection("bonnesboites") + .aggregate([ + { + $match: query, }, - }, - ]) + { + $sample: { + size: companyLimit, + }, + }, + ]) + .toArray()) as ILbaCompany[] } if (!latitude) { @@ -320,7 +322,7 @@ export const getCompanyFromSiret = async ({ } > => { try { - const lbaCompany = await LbaCompany.findOne({ siret }) + const lbaCompany = await getDbCollection("bonnesboites").findOne({ siret }) if (lbaCompany) { const applicationCountByCompany = await getApplicationByCompanyCount([lbaCompany.siret]) @@ -364,61 +366,72 @@ export const getCompanyFromSiret = async ({ * @returns {Promise} */ export const updateContactInfo = async ({ siret, email, phone }: { siret: string; email?: string; phone?: string }) => { + const now = new Date() try { - const lbaCompany = await LbaCompany.findOne({ siret }) - const fieldUpdates: IRecruteurLbaUpdateEventNew[] = [] + const lbaCompany = await getDbCollection("bonnesboites").findOne({ siret }) + const fieldUpdates: IRecruteurLbaUpdateEvent[] = [] if (!lbaCompany) { throw Boom.badRequest() } + if (email !== undefined) { + await getDbCollection("bonnesboites").findOneAndUpdate({ siret }, { $set: { email } }) + } + + if (phone !== undefined) { + await getDbCollection("bonnesboites").findOneAndUpdate({ siret }, { $set: { phone } }) + } if (lbaCompany.email !== email) { if (!email) { - fieldUpdates.push( - new RecruteurLbaUpdateEvent({ - siret, - value: "", - event: ERecruteurLbaUpdateEventType.DELETE_EMAIL, - }) - ) + fieldUpdates.push({ + _id: new ObjectId(), + created_at: now, + siret, + value: "", + event: ERecruteurLbaUpdateEventType.DELETE_EMAIL, + }) + lbaCompany.email = "" } else { - fieldUpdates.push( - new RecruteurLbaUpdateEvent({ - siret, - value: email, - event: ERecruteurLbaUpdateEventType.UPDATE_EMAIL, - }) - ) + fieldUpdates.push({ + _id: new ObjectId(), + created_at: now, + siret, + value: email, + event: ERecruteurLbaUpdateEventType.UPDATE_EMAIL, + }) lbaCompany.email = email } } if (lbaCompany.phone !== phone) { if (!phone) { - fieldUpdates.push( - new RecruteurLbaUpdateEvent({ - siret, - value: "", - event: ERecruteurLbaUpdateEventType.DELETE_PHONE, - }) - ) + fieldUpdates.push({ + _id: new ObjectId(), + created_at: now, + siret, + value: "", + event: ERecruteurLbaUpdateEventType.DELETE_PHONE, + }) + lbaCompany.phone = "" } else { - fieldUpdates.push( - new RecruteurLbaUpdateEvent({ - siret, - value: phone, - event: ERecruteurLbaUpdateEventType.UPDATE_PHONE, - }) - ) + fieldUpdates.push({ + _id: new ObjectId(), + created_at: now, + siret, + value: phone, + event: ERecruteurLbaUpdateEventType.UPDATE_PHONE, + }) + lbaCompany.phone = phone } } await Promise.all([ - db.collection("bonnesboites").updateOne({ _id: lbaCompany._id }, { $set: { phone: lbaCompany.phone, email: lbaCompany.email, last_update_at: new Date() } }), + getDbCollection("bonnesboites").updateOne({ _id: lbaCompany._id }, { $set: { phone: lbaCompany.phone, email: lbaCompany.email, last_update_at: new Date() } }), ...fieldUpdates.map(async (update) => { - db.collection("recruteurlbaupdateevents").insertOne(update) + getDbCollection("recruteurlbaupdateevents").insertOne(update) }), ]) return { enseigne: lbaCompany.enseigne, phone: lbaCompany.phone, email: lbaCompany.email, siret: lbaCompany.siret } @@ -430,7 +443,7 @@ export const updateContactInfo = async ({ siret, email, phone }: { siret: string export const getCompanyContactInfo = async ({ siret }: { siret: string }): Promise => { try { - const lbaCompany = await LbaCompany.findOne({ siret }) + const lbaCompany = await getDbCollection("bonnesboites").findOne({ siret }) if (lbaCompany) { return { enseigne: lbaCompany.enseigne, phone: lbaCompany.phone, email: lbaCompany.email, siret: lbaCompany.siret } diff --git a/server/src/services/lbajob.service.ts b/server/src/services/lbajob.service.ts index e1ee95503b..e89194e78c 100644 --- a/server/src/services/lbajob.service.ts +++ b/server/src/services/lbajob.service.ts @@ -1,11 +1,10 @@ import Boom from "boom" -import pkg from "mongodb" +import { ObjectId } from "mongodb" import { IJob, IRecruiter, JOB_STATUS } from "shared" import { LBA_ITEM_TYPE_OLD } from "shared/constants/lbaitem" import { RECRUITER_STATUS } from "shared/constants/recruteur" -import { Cfa, Recruiter } from "@/common/model" -import { ObjectIdType, db } from "@/common/mongodb" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { encryptMailWithIV } from "../common/utils/encryptString" import { IApiError, manageApiError } from "../common/utils/errorManager" @@ -20,8 +19,6 @@ import { getOffreAvecInfoMandataire, romeDetailAggregateStages } from "./formula import { ILbaItemLbaJob } from "./lbaitem.shared.service.types" import { filterJobsByOpco } from "./opco.service" -const { ObjectId } = pkg - const JOB_SEARCH_LIMIT = 250 const FRANCE_LATITUDE = 46.227638 const FRANCE_LONGITUDE = 2.213749 @@ -95,7 +92,9 @@ export const getJobs = async ({ }, }) - const recruiters: IRecruiter[] = await Recruiter.aggregate(isMinimalData ? stages : [...stages, ...romeDetailAggregateStages]) + const recruiters: IRecruiter[] = (await getDbCollection("recruiters") + .aggregate(isMinimalData ? stages : [...stages, ...romeDetailAggregateStages]) + .toArray()) as IRecruiter[] const recruitersWithJobs = await Promise.all( recruiters.map(async (recruiter) => { @@ -105,7 +104,7 @@ export const getJobs = async ({ } if (recruiter.is_delegated && recruiter.cfa_delegated_siret) { - const cfa = await Cfa.findOne({ siret: recruiter.cfa_delegated_siret }) + const cfa = await getDbCollection("cfas").findOne({ siret: recruiter.cfa_delegated_siret }) const cfaUser = await getUser2ManagingOffer(firstJob) recruiter.phone = cfaUser.phone recruiter.email = cfaUser.email @@ -224,7 +223,7 @@ function transformLbaJobs({ jobs, applicationCountByJob, isMinimalData }: { jobs /** * @description Retourne une offre LBA identifiée par son id */ -export const getLbaJobById = async ({ id, caller }: { id: ObjectIdType; caller?: string }): Promise => { +export const getLbaJobById = async ({ id, caller }: { id: ObjectId; caller?: string }): Promise => { try { const rawJob = await getOffreAvecInfoMandataire(id) @@ -454,13 +453,14 @@ function sortLbaJobs(jobs: { results: ILbaItemLbaJob[] }) { */ export const addOffreDetailView = async (jobId: IJob["_id"] | string) => { try { - await db.collection("recruiters").updateOne( + await getDbCollection("recruiters").updateOne( { "jobs._id": jobId }, { $inc: { - "jobs.$.stats_detail_view": 1, + "jobs.$[elem].stats_detail_view": 1, }, - } + }, + { arrayFilters: [{ "elem._id": jobId }] } ) } catch (err) { sentryCaptureException(err) @@ -473,7 +473,7 @@ export const addOffreDetailView = async (jobId: IJob["_id"] | string) => { export const incrementLbaJobsViewCount = async (jobIds: string[]) => { const ids = jobIds.map((id) => new ObjectId(id)) try { - await db.collection("recruiters").updateMany( + await getDbCollection("recruiters").updateMany( { "jobs._id": { $in: ids } }, { $inc: { diff --git a/server/src/services/login.service.ts b/server/src/services/login.service.ts index d40269c5fb..73b3a1cf99 100644 --- a/server/src/services/login.service.ts +++ b/server/src/services/login.service.ts @@ -1,11 +1,12 @@ import Boom from "boom" +import { ObjectId } from "mongodb" import { assertUnreachable } from "shared" import { EntrepriseStatus } from "shared/models/entreprise.model" import { AccessEntityType, AccessStatus } from "shared/models/roleManagement.model" import { IUserWithAccount, UserEventType } from "shared/models/userWithAccount.model" import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" -import { Entreprise, RoleManagement } from "@/common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" export const controlUserState = async (user: IUserWithAccount): Promise<{ error: boolean; reason?: string }> => { const status = getLastStatusEvent(user.status)?.status @@ -14,7 +15,7 @@ export const controlUserState = async (user: IUserWithAccount): Promise<{ error: return { error: true, reason: "DISABLED" } case UserEventType.VALIDATION_EMAIL: case UserEventType.ACTIF: { - const roles = await RoleManagement.find({ user_id: user._id.toString() }).lean() + const roles = await getDbCollection("rolemanagements").find({ user_id: user._id }).toArray() const rolesWithAccess = roles.filter((role) => getLastStatusEvent(role.status)?.status === AccessStatus.GRANTED) const cfaOpcoOrAdminRoles = rolesWithAccess.filter((role) => [AccessEntityType.ADMIN, AccessEntityType.OPCO, AccessEntityType.CFA].includes(role.authorized_type)) if (cfaOpcoOrAdminRoles.length) { @@ -22,8 +23,10 @@ export const controlUserState = async (user: IUserWithAccount): Promise<{ error: } const entrepriseRoles = rolesWithAccess.filter((role) => role.authorized_type === AccessEntityType.ENTREPRISE) if (entrepriseRoles.length) { - const entreprises = await Entreprise.find({ _id: { $in: entrepriseRoles.map((role) => role.authorized_id) } }).lean() - const hasSomeEntrepriseReady = entreprises.some((entreprise) => getLastStatusEvent(entreprise.status)?.status === EntrepriseStatus.VALIDE) + const entreprises = await getDbCollection("entreprises") + .find({ _id: { $in: entrepriseRoles.map((role) => new ObjectId(role.authorized_id.toString())) } }) + .toArray() + const hasSomeEntrepriseReady = entreprises.find((entreprise) => getLastStatusEvent(entreprise.status)?.status === EntrepriseStatus.VALIDE) if (hasSomeEntrepriseReady) { return { error: false } } diff --git a/server/src/services/metiers.service.ts b/server/src/services/metiers.service.ts index ec15c6d025..38126d4f67 100644 --- a/server/src/services/metiers.service.ts +++ b/server/src/services/metiers.service.ts @@ -1,15 +1,15 @@ import Boom from "boom" import * as _ from "lodash-es" import { matchSorter } from "match-sorter" +import { IDiplomesMetiers, IDomainesMetiers } from "shared" import { removeAccents, removeRegexChars } from "shared/utils" import { logger } from "@/common/logger" -import { IDiplomesMetiers } from "@/common/model/schema/diplomesmetiers/diplomesmetiers.types" -import { IDomainesMetiers } from "@/common/model/schema/domainesmetiers/domainesmetiers.types" -import { db } from "@/common/mongodb" import { notifyToSlack } from "@/common/utils/slackUtils" import config from "@/config" +import { getDbCollection } from "../common/utils/mongodbUtils" + import { getRomesFromCatalogue } from "./catalogue.service" import { IAppellationsRomes, IMetierEnrichi, IMetiers, IMetiersEnrichis } from "./metiers.service.types" @@ -24,7 +24,7 @@ export const initializeCacheMetiers = async () => { if (!cacheMetierLoading) { cacheMetierLoading = true logger.info("initializeCacheMetiers on first use") - globalCacheMetiers = await db.collection("domainesmetiers").find({}).toArray() + globalCacheMetiers = await getDbCollection("domainesmetiers").find({}).toArray() cacheMetierLoading = false const roughObjSize = JSON.stringify(globalCacheMetiers).length if (config.env === "production") { @@ -42,7 +42,7 @@ export const initializeCacheDiplomas = async () => { if (!cacheDiplomaLoading) { cacheDiplomaLoading = true logger.info("initializeCacheDiplomas on first use") - globalCacheDiplomas = await db.collection("diplomesmetiers").find({}).toArray() + globalCacheDiplomas = await getDbCollection("diplomesmetiers").find({}).toArray() cacheDiplomaLoading = false const roughObjSize = JSON.stringify(globalCacheDiplomas).length if (config.env === "production") { diff --git a/server/src/services/opco.service.ts b/server/src/services/opco.service.ts index 2a158143c3..b83c902903 100644 --- a/server/src/services/opco.service.ts +++ b/server/src/services/opco.service.ts @@ -1,9 +1,9 @@ import memoize from "memoizee" import { OPCOS } from "shared/constants/recruteur" import { IReferentielOpco, ZReferentielOpcoInsert } from "shared/models" +import { IOpco } from "shared/models/opco.model" -import { Opco } from "../common/model/index" -import { IOpco } from "../common/model/schema/opco/opco.types" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { CFADOCK_FILTER_LIMIT, fetchOpcosFromCFADock } from "./cfadock.service" @@ -11,7 +11,7 @@ import { CFADOCK_FILTER_LIMIT, fetchOpcosFromCFADock } from "./cfadock.service" * @description get opco from database collection OPCOS */ export const getOpcoBySirenFromDB = async (siren: string) => { - const opcoFromDB = await Opco.findOne({ siren }) + const opcoFromDB = await getDbCollection("opcos").findOne({ siren }) if (opcoFromDB) { const { opco, idcc } = opcoFromDB return { opco, idcc } @@ -19,11 +19,11 @@ export const getOpcoBySirenFromDB = async (siren: string) => { } /** - * @description tente d'ajouter un opco en base et retourne une string indiquant le résultat + * @description ajoute un opco en base s'il n'existe pas déjà sinon le mets à jour * @param {IOpco} opcoData * @returns {Promise} */ -export const saveOpco = async (opcoData: IOpco) => Opco.findOneAndUpdate({ siren: opcoData.siren }, opcoData, { upsert: true }) +export const saveOpco = async (opcoData: Omit) => getDbCollection("opcos").findOneAndUpdate({ siren: opcoData.siren }, { $set: opcoData }, { upsert: true }) /** * @description retourne le nom court d'un opco en paramètre @@ -73,7 +73,7 @@ export const filterJobsByOpco = async ({ jobs, opco, opcoUrl }: { jobs: any[]; o searchForOpcoParams.opco = OPCOS[opco.toUpperCase()] } - const foundInMongoOpcos = await Opco.find(searchForOpcoParams) + const foundInMongoOpcos = await getDbCollection("opcos").find(searchForOpcoParams).toArray() let opcoFilteredSirens: any[] = [] diff --git a/server/src/services/organization.service.ts b/server/src/services/organization.service.ts index a935e24105..4e0794b84d 100644 --- a/server/src/services/organization.service.ts +++ b/server/src/services/organization.service.ts @@ -1,12 +1,13 @@ import Boom from "boom" +import { ObjectId } from "mongodb" import { ICFA } from "shared/models/cfa.model" import { EntrepriseStatus, IEntreprise } from "shared/models/entreprise.model" import { AccessEntityType, AccessStatus } from "shared/models/roleManagement.model" import { IUserWithAccount } from "shared/models/userWithAccount.model" import { getLastStatusEvent } from "shared/utils" -import { Entreprise, Recruiter, RoleManagement, UserWithAccount } from "@/common/model" -import { asyncForEach } from "@/common/utils/asyncUtils" +import { asyncForEach } from "../common/utils/asyncUtils" +import { getDbCollection } from "../common/utils/mongodbUtils" import { CFA, ENTREPRISE } from "./constant.service" import { autoValidateUserRoleOnCompany, getEntrepriseDataFromSiret, sendEmailConfirmationEntreprise } from "./etablissement.service" @@ -17,11 +18,11 @@ export type Organization = { entreprise: IEntreprise; type: typeof ENTREPRISE } export type UserAndOrganization = { user: IUserWithAccount; organization: Organization } export const updateEntrepriseOpco = async (siret: string, { opco, idcc }: { opco: string; idcc?: string }) => { - const entreprise = await Entreprise.findOne({ siret }).lean() + const entreprise = await getDbCollection("entreprises").findOne({ siret }) if (!entreprise) { throw new Error("inattendu: aucune entreprise trouvée. Merci d'appeler cette méthode une fois l'entreprise créée") } - await Entreprise.findOneAndUpdate({ siret }, { opco, idcc }).lean() + await getDbCollection("entreprises").findOneAndUpdate({ siret }, { $set: { opco, idcc } }) } /** @@ -37,10 +38,12 @@ export const upsertEntrepriseData = async ( siretResponse: Awaited>, isInternalError: boolean ): Promise => { - let existingEntreprise = await Entreprise.findOne({ siret }).lean() + let existingEntreprise: IEntreprise | null = await getDbCollection("entreprises").findOne({ siret }) if ("error" in siretResponse) { if (!existingEntreprise) { - existingEntreprise = (await Entreprise.create({ siret, origin, status: [] })).toObject() + const now = new Date() + existingEntreprise = { _id: new ObjectId(), createdAt: now, updatedAt: now, siret, origin, status: [] } + await getDbCollection("entreprises").insertOne(existingEntreprise) } if (isInternalError) { const statusToUpdate = [EntrepriseStatus.ERROR, EntrepriseStatus.A_METTRE_A_JOUR] @@ -51,7 +54,7 @@ export const upsertEntrepriseData = async ( } else { await deactivateEntreprise(existingEntreprise._id, siretResponse.message) } - return Entreprise.findOne({ siret }).lean() + return (await getDbCollection("entreprises").findOne({ siret }))! } const { address, address_detail, establishment_enseigne, geo_coordinates, establishment_raison_sociale } = siretResponse @@ -65,18 +68,26 @@ export const upsertEntrepriseData = async ( } let savedEntreprise: IEntreprise if (existingEntreprise) { - savedEntreprise = await Entreprise.findOneAndUpdate({ siret }, { $set: entrepriseFields }, { new: true }).lean() + const updatedEntreprise = await getDbCollection("entreprises").findOneAndUpdate({ siret }, { $set: entrepriseFields }, { returnDocument: "after" }) + if (!updatedEntreprise) { + throw Boom.internal("inattendu: aucune entreprise trouvée") + } + savedEntreprise = updatedEntreprise } else { - savedEntreprise = (await Entreprise.create({ ...entrepriseFields, siret, origin })).toObject() + const now = new Date() + savedEntreprise = { ...entrepriseFields, siret, origin, _id: new ObjectId(), createdAt: now, updatedAt: now, status: [] } + await getDbCollection("entreprises").insertOne(savedEntreprise) } await setEntrepriseValid(savedEntreprise._id) - await Recruiter.updateMany({ establishment_siret: siret }, siretResponse) + await getDbCollection("recruiters").updateMany({ establishment_siret: siret }, { $set: siretResponse }) if (getLastStatusEvent(existingEntreprise?.status)?.status === EntrepriseStatus.ERROR) { - const recruiters = await Recruiter.find({ establishment_siret: siret }).lean() - const roles = await RoleManagement.find({ authorized_type: AccessEntityType.ENTREPRISE, authorized_id: savedEntreprise._id.toString() }).lean() + const recruiters = await getDbCollection("recruiters").find({ establishment_siret: siret }).toArray() + const roles = await getDbCollection("rolemanagements").find({ authorized_type: AccessEntityType.ENTREPRISE, authorized_id: savedEntreprise._id.toString() }).toArray() const rolesToUpdate = roles.filter((role) => getLastStatusEvent(role.status)?.status !== AccessStatus.DENIED) - const users = await UserWithAccount.find({ _id: { $in: rolesToUpdate.map((role) => role.user_id) } }).lean() + const users = await getDbCollection("userswithaccounts") + .find({ _id: { $in: rolesToUpdate.map((role) => role.user_id) } }) + .toArray() await asyncForEach(users, async (user) => { const userAndOrganization: UserAndOrganization = { user, organization: { entreprise: savedEntreprise, type: ENTREPRISE } } const result = await autoValidateUserRoleOnCompany(userAndOrganization, origin) diff --git a/server/src/services/referrers.service.ts b/server/src/services/referrers.service.ts new file mode 100644 index 0000000000..91bee90e24 --- /dev/null +++ b/server/src/services/referrers.service.ts @@ -0,0 +1,16 @@ +import Boom from "boom" +import { ReferrerObject, referrers } from "shared/constants/referers" + +function isReferrer(name: string): name is keyof typeof referrers { + return Object.keys(referrers).includes(name) +} + +export function getReferrerByKeyName(name: string | null | undefined): ReferrerObject { + if (!name) throw Boom.badRequest("Referrer introuvable.") + const upperName = name.toUpperCase() + if (!isReferrer(upperName)) { + throw Boom.badRequest("Referrer introuvable.") + } + const referrerFound = referrers[upperName] + return referrerFound +} diff --git a/server/src/services/roleManagement.service.ts b/server/src/services/roleManagement.service.ts index 382744d778..c2dd5feb89 100644 --- a/server/src/services/roleManagement.service.ts +++ b/server/src/services/roleManagement.service.ts @@ -1,5 +1,5 @@ import Boom from "boom" -import type { ObjectId } from "mongodb" +import { ObjectId } from "mongodb" import { ADMIN, CFA, ENTREPRISE, ETAT_UTILISATEUR, OPCO, OPCOS } from "shared/constants/recruteur" import { ComputedUserAccess, IUserRecruteurPublic } from "shared/models" import { ICFA } from "shared/models/cfa.model" @@ -8,7 +8,7 @@ import { AccessEntityType, AccessStatus, IRoleManagement, IRoleManagementEvent } import { parseEnum, parseEnumOrError } from "shared/utils" import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" -import { Cfa, Entreprise, RoleManagement, UserWithAccount } from "@/common/model" +import { getDbCollection } from "../common/utils/mongodbUtils" import { getFormulaireFromUserIdOrError } from "./formulaire.service" @@ -16,44 +16,55 @@ export const modifyPermissionToUser = async ( props: Pick, eventProps: Pick ): Promise => { + const now = new Date() const event: IRoleManagementEvent = { ...eventProps, - date: new Date(), + date: now, } const { authorized_id, authorized_type, user_id } = props - const role = await RoleManagement.findOne({ authorized_id, authorized_type, user_id }).lean() + const role = await getDbCollection("rolemanagements").findOne({ authorized_id, authorized_type, user_id }) + if (role) { const lastEvent = getLastStatusEvent(role.status) if (lastEvent?.status === eventProps.status) { return role } - const newRole = await RoleManagement.findOneAndUpdate({ _id: role._id }, { $push: { status: event } }, { new: true }).lean() + const newRole = await getDbCollection("rolemanagements").findOneAndUpdate( + { _id: role._id }, + { $push: { status: event }, $set: { updatedAt: new Date() } }, + { returnDocument: "after" } + ) if (!newRole) { throw Boom.internal("inattendu") } return newRole } else { - const newRole: Omit = { + const newRole: IRoleManagement = { ...props, + _id: new ObjectId(), status: [event], + updatedAt: now, + createdAt: now, } - const role = (await RoleManagement.create(newRole)).toObject() - return role + await getDbCollection("rolemanagements").insertOne(newRole) + return newRole } } export const getGrantedRoles = async (userId: string) => { - const roles = await RoleManagement.find({ user_id: userId }).lean() + const roles = await getDbCollection("rolemanagements") + .find({ user_id: new ObjectId(userId) }) + .toArray() return roles.filter((role) => getLastStatusEvent(role.status)?.status === AccessStatus.GRANTED) } // TODO à supprimer lorsque les utilisateurs pourront avoir plusieurs types -export const getMainRoleManagement = async (userId: string | ObjectId, includeUserAwaitingValidation: boolean = false): Promise => { +export const getMainRoleManagement = async (userId: ObjectId, includeUserAwaitingValidation: boolean = false): Promise => { const validStatus = [AccessStatus.GRANTED] if (includeUserAwaitingValidation) { validStatus.push(AccessStatus.AWAITING_VALIDATION) } - const allRoles = await RoleManagement.find({ user_id: userId }).lean() + const allRoles = await getDbCollection("rolemanagements").find({ user_id: userId }).toArray() const roles = allRoles.filter((role) => { const status = getLastStatusEvent(role.status)?.status return status ? validStatus.includes(status) : false @@ -99,7 +110,7 @@ const roleToStatus = (role: IRoleManagement) => { } export const getPublicUserRecruteurPropsOrError = async ( - userId: string | ObjectId, + userId: ObjectId, includeUserAwaitingValidation: boolean = false ): Promise> => { const mainRole = await getMainRoleManagement(userId, includeUserAwaitingValidation) @@ -119,7 +130,7 @@ export const getPublicUserRecruteurPropsOrError = async ( status_current, } as const if (type === CFA) { - const cfa = await Cfa.findOne({ _id: mainRole.authorized_id }).lean() + const cfa = await getDbCollection("cfas").findOne({ _id: new ObjectId(mainRole.authorized_id) }) if (!cfa) { throw Boom.internal(`inattendu : cfa non trouvé pour user id=${userId}`) } @@ -127,12 +138,12 @@ export const getPublicUserRecruteurPropsOrError = async ( return { ...commonFields, establishment_siret: siret } } if (type === ENTREPRISE) { - const entreprise = await Entreprise.findOne({ _id: mainRole.authorized_id }).lean() + const entreprise = await getDbCollection("entreprises").findOne({ _id: new ObjectId(mainRole.authorized_id.toString()) }) if (!entreprise) { throw Boom.internal(`inattendu : entreprise non trouvée pour user id=${userId}`) } const { siret } = entreprise - const user = await UserWithAccount.findOne({ _id: userId }).lean() + const user = await getDbCollection("userswithaccounts").findOne({ _id: userId }) if (!user) { throw Boom.internal(`inattendu : user non trouvé`, { userId }) } @@ -169,14 +180,14 @@ export const getComputedUserAccess = (userId: string, grantedRoles: IRoleManagem export const getOrganizationFromRole = async (role: IRoleManagement): Promise => { switch (role.authorized_type) { case AccessEntityType.CFA: { - const cfaOpt = await Cfa.findOne({ _id: role.authorized_id }) + const cfaOpt = await getDbCollection("cfas").findOne({ _id: new ObjectId(role.authorized_id) }) if (!cfaOpt) { throw new Error(`inattendu: impossible de trouver le cfa pour le role id=${role._id}`) } return cfaOpt } case AccessEntityType.ENTREPRISE: { - const entrepriseOpt = await Entreprise.findOne({ _id: role.authorized_id }) + const entrepriseOpt = await getDbCollection("entreprises").findOne({ _id: new ObjectId(role.authorized_id) }) if (!entrepriseOpt) { throw new Error(`inattendu: impossible de trouver l'entreprise pour le role id=${role._id}`) } diff --git a/server/src/services/rome.service.ts b/server/src/services/rome.service.ts index a6cb1e84fe..6727107acc 100644 --- a/server/src/services/rome.service.ts +++ b/server/src/services/rome.service.ts @@ -1,4 +1,12 @@ -import { ReferentielRome } from "../common/model" +import { getDbCollection } from "@/common/utils/mongodbUtils" -export const getRomeDetailsFromDB = async (romeCode: string) => ReferentielRome.findOne({ "rome.code_rome": romeCode }).select({ _id: 0 }).lean() -export const getFicheMetierFromDB = async ({ query }) => ReferentielRome.findOne(query).lean() +export const getRomeDetailsFromDB = async (romeCode: string) => + getDbCollection("referentielromes").findOne( + { "rome.code_rome": romeCode }, + { + projection: { + _id: 0, + }, + } + ) +export const getFicheMetierFromDB = async ({ query }) => getDbCollection("referentielromes").findOne(query) diff --git a/server/src/services/sessions.service.ts b/server/src/services/sessions.service.ts index c3198ae11c..ad7f8632a4 100644 --- a/server/src/services/sessions.service.ts +++ b/server/src/services/sessions.service.ts @@ -1,36 +1,37 @@ -import { FilterQuery, FindOneOptions, ObjectId } from "mongodb" +import { Filter, FindOptions, ObjectId } from "mongodb" import { ISession } from "shared" import config from "@/config" -import { Session } from "../common/model/index" +import { getDbCollection } from "../common/utils/mongodbUtils" type TCreateSession = Pick export const createSession = async (data: TCreateSession) => { const now = new Date() - const sessionObj = new Session({ + const sessionObj: ISession = { ...data, + _id: new ObjectId(), updated_at: now, created_at: now, expires_at: new Date(now.getTime() + config.auth.session.cookie.maxAge), - }) - await sessionObj.save() + } + const { insertedId } = await getDbCollection("sessions").insertOne(sessionObj) - const session = await getSession({ _id: sessionObj._id }) + const session = await getSession({ _id: insertedId }) return session } -export const getSession = async (filter: FilterQuery, options?: FindOneOptions): Promise => { - return Session.findOne(filter, options) +export const getSession = async (filter: Filter, options?: FindOptions): Promise => { + return getDbCollection("sessions").findOne(filter, options) } export const deleteSession = async (token: string) => { - await Session.deleteMany({ token }) + await getDbCollection("sessions").deleteMany({ token }) } export const updateSession = async (_id: ObjectId, data: Partial) => { - return Session.updateOne({ _id }, { $set: { ...data, updated_at: new Date() } }) + return getDbCollection("sessions").updateOne({ _id }, { $set: { ...data, updated_at: new Date() } }) } diff --git a/server/src/services/trainingLinks.service.ts b/server/src/services/trainingLinks.service.ts index a357d4928b..a5c5f52542 100644 --- a/server/src/services/trainingLinks.service.ts +++ b/server/src/services/trainingLinks.service.ts @@ -4,7 +4,8 @@ import { URL } from "url" import { getDistance } from "geolib" import { IFormationCatalogue } from "shared/models" -import { EligibleTrainingsForAppointment, FormationCatalogue } from "../common/model/index" +import { getDbCollection } from "@/common/utils/mongodbUtils" + import apiGeoAdresse from "../common/utils/apiGeoAdresse" import { asyncForEach } from "../common/utils/asyncUtils" import config from "../config.js" @@ -54,7 +55,7 @@ const getFormations = ( rome_codes: 1, _id: 0, } -) => FormationCatalogue.find(query, filter) +) => getDbCollection("formationcatalogues").find(query, filter).toArray() /** * @description get formation according to the available parameters passed to the API endpoint @@ -105,7 +106,7 @@ const getPrdvLink = async (wish: IWish): Promise => { return "" } - const elligibleFormation = await EligibleTrainingsForAppointment.findOne( + const elligibleFormation = await getDbCollection("eligible_trainings_for_appointments").findOne( { cle_ministere_educatif: wish.cle_ministere_educatif, lieu_formation_email: { @@ -114,7 +115,7 @@ const getPrdvLink = async (wish: IWish): Promise => { $not: /^$/, }, }, - { _id: 1 } + { projection: { _id: 1 } } ) if (elligibleFormation) { @@ -129,25 +130,30 @@ const getPrdvLink = async (wish: IWish): Promise => { const getRomesGlobaux = async ({ rncp, cfd, mef }) => { let romes = [] as string[] - const tmpFormations = await FormationCatalogue.find( - { - $or: [ - { - rncp_code: rncp, - }, - { - cfd: cfd ? cfd : undefined, - }, - { - "bcn_mefs_10.mef10": mef, + const tmpFormations = await getDbCollection("formationcatalogues") + .find( + { + $or: [ + { + rncp_code: rncp, + }, + { + cfd: cfd ? cfd : undefined, + }, + { + "bcn_mefs_10.mef10": mef, + }, + ], + }, + { + projection: { + rome_codes: 1, + _id: 0, }, - ], - }, - { - rome_codes: 1, - _id: 0, - } - ).limit(5) + } + ) + .limit(5) + .toArray() if (tmpFormations.length) { romes = [...new Set(tmpFormations.flatMap(({ rome_codes }) => rome_codes))] as string[] } diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index 5f33f19dff..0e465fb02b 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -1,19 +1,17 @@ import Boom from "boom" -import type { FilterQuery } from "mongoose" +import { ObjectId } from "mongodb" import { IUser } from "shared" import { ETAT_UTILISATEUR, OPCOS } from "shared/constants/recruteur" import { IUserForOpco } from "shared/routes/user.routes" import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" -import { ObjectId } from "@/common/mongodb" - -import { Recruiter, User, UserWithAccount } from "../common/model/index" +import { getDbCollection } from "@/common/utils/mongodbUtils" import { getUserRecruteursForManagement } from "./userRecruteur.service" -const createOrUpdateUserByEmail = async (email: string, update: Partial, create: Partial): Promise<{ user: IUser; isNew: boolean }> => { +export const createOrUpdateUserByEmail = async (email: string, update: Partial, create: Partial): Promise<{ user: IUser; isNew: boolean }> => { const newUserId = new ObjectId() - const user = await User.findOneAndUpdate( + await getDbCollection("users").findOneAndUpdate( { email }, { $set: update, @@ -21,74 +19,26 @@ const createOrUpdateUserByEmail = async (email: string, update: Partial, }, { upsert: true, - new: true, } ) + const savedUser = await getDbCollection("users").findOne({ email }) + if (!savedUser) { + throw Boom.internal("inattendu : user non sauvegardé") + } return { - user, + user: savedUser, // If the user is new, we will have to update the _id with the default one - isNew: user._id.equals(newUserId), + isNew: savedUser._id.equals(newUserId), } } -/** - * @description Returns user from its email. - * @param {string} email - * @returns {Promise} - */ -const getUserByMail = (email: string) => User.findOne({ email }) - /** * @description Returns user from its identifier. * @param {string} userId * @returns {Promise} */ -const getUserById = (userId: string) => User.findById(userId) - -/** - * @description Updates item. - * @param {String} id - ObjectId - * @param {User} params - * @returns {Promise} - */ -const update = (id: string, params) => User.findOneAndUpdate({ _id: id }, params, { new: true }) - -/** - * @description Creates an user. - * @param {String} username - * @param {String} password - * @param {User} options - * @returns {Promise} - */ -const createUser = async (options: Partial) => { - const { firstname, lastname, phone, email, role, type } = options - - const user = new User({ - firstname, - lastname, - phone, - email, - role, - type, - }) - - return user.save() -} - -/** - * @description Returns items. - * @param {FilterQuery} conditions - * @returns {Promise} - */ -const find = (conditions: FilterQuery) => User.find(conditions) - -/** - * @description Returns one item. - * @param {FilterQuery} conditions - * @returns {Promise} - */ -const findOne = (conditions: FilterQuery) => User.findOne(conditions) +export const getUserById = (userId: string) => getDbCollection("users").findOne({ _id: new ObjectId(userId) }) export const getUserAndRecruitersDataForOpcoUser = async ( opco: OPCOS @@ -100,9 +50,9 @@ export const getUserAndRecruitersDataForOpcoUser = async ( const userRecruteurs = await getUserRecruteursForManagement({ opco }) const filteredUserRecruteurs = [...userRecruteurs.active, ...userRecruteurs.awaiting, ...userRecruteurs.disabled] const userIds = [...new Set(filteredUserRecruteurs.map(({ _id }) => _id.toString()))] - const recruiters = await Recruiter.find({ "jobs.managed_by": { $in: userIds } }) - .select({ establishment_id: 1, origin: 1, jobs: 1, _id: 0 }) - .lean() + const recruiters = await getDbCollection("recruiters") + .find({ "jobs.managed_by": { $in: userIds } }, { projection: { establishment_id: 1, origin: 1, jobs: 1, _id: 0 } }) + .toArray() const recruiterMap = new Map() recruiters.forEach((recruiter) => { @@ -157,9 +107,9 @@ export const getUserAndRecruitersDataForOpcoUser = async ( } export const getUserNamesFromIds = async (ids: string[]) => { - const deduplicatedIds = [...new Set(ids)].filter((id) => ObjectId.isValid(id)) - const users = await UserWithAccount.find({ _id: { $in: deduplicatedIds } }).lean() + const deduplicatedIds = [...new Set(ids)].filter((id) => ObjectId.isValid(id)).map((id) => new ObjectId(id)) + const users = await getDbCollection("userswithaccounts") + .find({ _id: { $in: deduplicatedIds } }) + .toArray() return users } - -export { createOrUpdateUserByEmail, createUser, find, findOne, getUserById, getUserByMail, update } diff --git a/server/src/services/userRecruteur.service.ts b/server/src/services/userRecruteur.service.ts index 7a8b0e4821..f842217775 100644 --- a/server/src/services/userRecruteur.service.ts +++ b/server/src/services/userRecruteur.service.ts @@ -1,6 +1,5 @@ -import { randomUUID } from "crypto" - import Boom from "boom" +import { ObjectId } from "mongodb" import { IRecruiter, IUserRecruteur, IUserRecruteurForAdmin, IUserStatusValidation, assertUnreachable, removeUndefinedFields } from "shared" import { BusinessErrorCodes } from "shared/constants/errorCodes" import { ADMIN, CFA, ENTREPRISE, ETAT_UTILISATEUR, OPCO, OPCOS, VALIDATION_UTILISATEUR } from "shared/constants/recruteur" @@ -10,11 +9,10 @@ import { AccessEntityType, AccessStatus, IRoleManagement, IRoleManagementEvent } import { IUserWithAccount, IUserWithAccountFields } from "shared/models/userWithAccount.model" import { getLastStatusEvent } from "shared/utils/getLastStatusEvent" -import { ObjectId, ObjectIdType } from "@/common/mongodb" import { getStaticFilePath } from "@/common/utils/getStaticFilePath" import { userWithAccountToUserForToken } from "@/security/accessTokenService" -import { Cfa, Entreprise, Recruiter, RoleManagement, UserWithAccount } from "../common/model/index" +import { getDbCollection } from "../common/utils/mongodbUtils" import config from "../config" import { createAuthMagicLink } from "./appLinks.service" @@ -24,12 +22,6 @@ import { Organization, UserAndOrganization } from "./organization.service" import { getOrganizationFromRole, modifyPermissionToUser } from "./roleManagement.service" import { createUser2IfNotExist, isUserEmailChecked } from "./userWithAccount.service" -/** - * @description generate an API key - * @returns {string} - */ -export const createApiKey = (): string => `mna-${randomUUID()}` - const entrepriseStatusEventToUserRecruteurStatusEvent = (entrepriseStatusEvent: IEntrepriseStatusEvent, forcedStatus: ETAT_UTILISATEUR): IUserStatusValidation => { const { reason, validation_type, granted_by } = entrepriseStatusEvent return { @@ -54,7 +46,7 @@ const roleStatusToUserRecruteurStatus = (roleStatus: AccessStatus): ETAT_UTILISA } } -export const getUserRecruteurById = (id: string | ObjectIdType) => getUserRecruteurByUser2Query({ _id: typeof id === "string" ? new ObjectId(id) : id }) +export const getUserRecruteurById = (id: string | ObjectId) => getUserRecruteurByUser2Query({ _id: typeof id === "string" ? new ObjectId(id) : id }) export const userAndRoleAndOrganizationToUserRecruteur = ( user: IUserWithAccount, @@ -122,9 +114,9 @@ export const userAndRoleAndOrganizationToUserRecruteur = ( } const getUserRecruteurByUser2Query = async (user2query: Partial): Promise => { - const user = await UserWithAccount.findOne(user2query).lean() + const user = await getDbCollection("userswithaccounts").findOne(user2query) if (!user) return null - const role = await RoleManagement.findOne({ user_id: user._id.toString() }).lean() + const role = await getDbCollection("rolemanagements").findOne({ user_id: user._id }) if (!role) return null const organization = await getOrganizationFromRole(role) if (!organization) return null @@ -226,26 +218,37 @@ export const createAdminUser = async (userProps: IUserWithAccountFields, { grant return user } -export const updateUserWithAccountFields = async (userId: ObjectIdType, fields: Partial): Promise => { +export const updateUserWithAccountFields = async (userId: ObjectId, fields: Partial): Promise => { const { email, first_name, last_name, phone } = fields const newEmail = email?.toLocaleLowerCase() if (newEmail) { - const exist = await UserWithAccount.findOne({ email: newEmail, _id: { $ne: userId } }).lean() + const exist = await getDbCollection("userswithaccounts").findOne({ email: newEmail, _id: { $ne: userId } }) if (exist) { return { error: BusinessErrorCodes.EMAIL_ALREADY_EXISTS } } } - const newUser = await UserWithAccount.findOneAndUpdate({ _id: userId }, removeUndefinedFields({ ...fields, email: newEmail }), { new: true }).lean() + + const updatedFields = removeUndefinedFields({ ...fields, email: newEmail, updatedAt: new Date() }) + const newUser = await getDbCollection("userswithaccounts").findOneAndUpdate( + { _id: userId }, + { $set: updatedFields }, + { + returnDocument: "after", + } + ) if (!newUser) { throw Boom.badRequest("user not found") } - await Recruiter.updateMany({ "jobs.managed_by": userId.toString() }, { $set: removeUndefinedFields({ first_name, last_name, phone, email: newEmail }) }) + await getDbCollection("recruiters").updateMany( + { "jobs.managed_by": userId.toString() }, + { $set: { ...removeUndefinedFields({ first_name, last_name, phone, email: newEmail }), updatedAt: new Date() } } + ) return newUser } export const removeUser = async (id: IUserWithAccount["_id"] | string) => { - await RoleManagement.deleteMany({ user_id: id }) + await getDbCollection("rolemanagements").deleteMany({ user_id: new ObjectId(id.toString()) }) } /** @@ -254,7 +257,7 @@ export const removeUser = async (id: IUserWithAccount["_id"] | string) => { * @returns {Promise} */ export const updateLastConnectionDate = async (email: IUserRecruteur["email"]): Promise => { - await UserWithAccount.findOneAndUpdate({ email: email.toLowerCase() }, { last_action_date: new Date() }, { new: true }).lean() + await getDbCollection("userswithaccounts").updateOne({ email: email.toLowerCase() }, { $set: { last_action_date: new Date(), updatedAt: new Date() } }) } /** @@ -279,8 +282,8 @@ export const setEntrepriseInError = async (entrepriseId: IEntreprise["_id"], rea return setEntrepriseStatus(entrepriseId, reason, EntrepriseStatus.ERROR) } -const setEntrepriseStatus = async (entrepriseId: IEntreprise["_id"], reason: string, status: EntrepriseStatus) => { - const entreprise = await Entreprise.findOne({ _id: entrepriseId }) +export const setEntrepriseStatus = async (entrepriseId: IEntreprise["_id"], reason: string, status: EntrepriseStatus) => { + const entreprise = await getDbCollection("entreprises").findOne({ _id: entrepriseId }) if (!entreprise) { throw Boom.internal(`could not find entreprise with id=${entrepriseId}`) } @@ -292,12 +295,15 @@ const setEntrepriseStatus = async (entrepriseId: IEntreprise["_id"], reason: str status, validation_type: VALIDATION_UTILISATEUR.AUTO, } - await Entreprise.updateOne( + await getDbCollection("entreprises").updateOne( { _id: entrepriseId }, { $push: { status: event, }, + $set: { + updatedAt: new Date(), + }, } ) } @@ -334,12 +340,17 @@ export const deactivateEntreprise = async (entrepriseId: IEntreprise["_id"], rea export const sendWelcomeEmailToUserRecruteur = async (user: IUserWithAccount) => { const { email, first_name, last_name } = user - const role = await RoleManagement.findOne({ user_id: user._id, authorized_type: { $in: [AccessEntityType.ENTREPRISE, AccessEntityType.CFA] } }).lean() + const role = await getDbCollection("rolemanagements").findOne({ user_id: user._id, authorized_type: { $in: [AccessEntityType.ENTREPRISE, AccessEntityType.CFA] } }) if (!role) { throw Boom.internal(`inattendu : pas de role pour user id=${user._id}`) } const isCfa = role.authorized_type === AccessEntityType.CFA - const organization = await (isCfa ? Cfa : Entreprise).findOne({ _id: role.authorized_id }).lean() + let organization + if (isCfa) { + organization = await getDbCollection("cfas").findOne({ _id: new ObjectId(role.authorized_id) }) + } else { + organization = await getDbCollection("entreprises").findOne({ _id: new ObjectId(role.authorized_id.toString()) }) + } if (!organization) { throw Boom.internal(`inattendu : pas d'organization pour user id=${user._id} et role id=${role._id}`) } @@ -362,12 +373,16 @@ export const sendWelcomeEmailToUserRecruteur = async (user: IUserWithAccount) => } export const getAdminUsers = async () => { - const allRoles = await RoleManagement.find({ - authorized_type: { $in: [AccessEntityType.ADMIN, AccessEntityType.OPCO] }, - }).lean() + const allRoles = await getDbCollection("rolemanagements") + .find({ + authorized_type: { $in: [AccessEntityType.ADMIN, AccessEntityType.OPCO] }, + }) + .toArray() const grantedRoles = allRoles.filter((role) => getLastStatusEvent(role.status)?.status === AccessStatus.GRANTED) - const userIds = grantedRoles.map((role) => role.user_id.toString()) - const users = await UserWithAccount.find({ _id: { $in: userIds } }).lean() + const userIds = grantedRoles.map((role) => role.user_id) + const users = await getDbCollection("userswithaccounts") + .find({ _id: { $in: userIds } }) + .toArray() return users.map((user) => { return { ...user, @@ -377,21 +392,32 @@ export const getAdminUsers = async () => { } export const getUserRecruteursForManagement = async ({ opco, activeRoleLimit }: { opco?: OPCOS; activeRoleLimit?: number }) => { - const nonGrantedRoles = await RoleManagement.find({ $expr: { $ne: [{ $arrayElemAt: ["$status.status", -1] }, AccessStatus.GRANTED] } }).lean() - const lastGrantedRoles = await RoleManagement.find({ $expr: { $eq: [{ $arrayElemAt: ["$status.status", -1] }, AccessStatus.GRANTED] } }) + const nonGrantedRoles = await getDbCollection("rolemanagements") + .find({ $expr: { $ne: [{ $arrayElemAt: ["$status.status", -1] }, AccessStatus.GRANTED] } }) + .toArray() + const lastGrantedRoles = await getDbCollection("rolemanagements") + .find({ $expr: { $eq: [{ $arrayElemAt: ["$status.status", -1] }, AccessStatus.GRANTED] } }) .sort({ updatedAt: -1 }) .limit(activeRoleLimit ?? 1000) - .lean() + .toArray() const roles = [...nonGrantedRoles, ...lastGrantedRoles] - const userIds = roles.map((role) => role.user_id.toString()) - const users = await UserWithAccount.find({ _id: { $in: userIds } }).lean() - - const entrepriseIds = roles.flatMap((role) => (role.authorized_type === AccessEntityType.ENTREPRISE ? [role.authorized_id] : [])) - const entreprises = await Entreprise.find({ _id: { $in: entrepriseIds }, ...(opco ? { opco } : {}) }).lean() - - const cfaIds = opco ? [] : roles.flatMap((role) => (role.authorized_type === AccessEntityType.CFA ? [role.authorized_id] : [])) - const cfas = cfaIds.length ? await Cfa.find({ _id: { $in: cfaIds } }).lean() : [] + const userIds = roles.map((role) => role.user_id) + const users = await getDbCollection("userswithaccounts") + .find({ _id: { $in: userIds } }) + .toArray() + + const entrepriseIds = roles.flatMap((role) => (role.authorized_type === AccessEntityType.ENTREPRISE ? [new ObjectId(role.authorized_id.toString())] : [])) + const entreprises = await getDbCollection("entreprises") + .find({ _id: { $in: entrepriseIds }, ...(opco ? { opco } : {}) }) + .toArray() + + const cfaIds = opco ? [] : roles.flatMap((role) => (role.authorized_type === AccessEntityType.CFA ? [new ObjectId(role.authorized_id)] : [])) + const cfas = cfaIds.length + ? await getDbCollection("cfas") + .find({ _id: { $in: cfaIds } }) + .toArray() + : [] const userRecruteurs = roles .flatMap<{ user: IUserWithAccount; role: IRoleManagement } & ({ entreprise: IEntreprise } | { cfa: ICFA })>((role) => { diff --git a/server/src/services/userWithAccount.service.ts b/server/src/services/userWithAccount.service.ts index b66b1e2d1f..12418c0157 100644 --- a/server/src/services/userWithAccount.service.ts +++ b/server/src/services/userWithAccount.service.ts @@ -1,4 +1,5 @@ import Boom from "boom" +import { ObjectId } from "mongodb" import { INewSuperUser } from "shared" import { ADMIN, OPCO } from "shared/constants" import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur" @@ -6,10 +7,10 @@ import { AccessStatus } from "shared/models/roleManagement.model" import { IUserStatusEvent, IUserWithAccount, UserEventType } from "shared/models/userWithAccount.model" import { assertUnreachable, getLastStatusEvent } from "shared/utils" -import { RoleManagement, UserWithAccount } from "@/common/model" -import { ObjectId } from "@/common/mongodb" import { createAdminUser, createOpcoUser } from "@/services/userRecruteur.service" +import { getDbCollection } from "../common/utils/mongodbUtils" + export const createUser2IfNotExist = async ( userProps: Omit, is_email_checked: boolean, @@ -18,45 +19,48 @@ export const createUser2IfNotExist = async ( const { first_name, last_name, last_action_date, origin, phone } = userProps const formatedEmail = userProps.email.toLocaleLowerCase() - let user = await UserWithAccount.findOne({ email: formatedEmail }).lean() - if (user) { - return user - } - const id = new ObjectId() - grantedBy = grantedBy || id.toString() - const status: IUserStatusEvent[] = [] - if (is_email_checked) { + let user = await getDbCollection("userswithaccounts").findOne({ email: formatedEmail }) + if (!user) { + const id = new ObjectId() + grantedBy = grantedBy || id.toString() + const status: IUserStatusEvent[] = [] + if (is_email_checked) { + status.push({ + date: new Date(), + reason: "validation de l'email à la création", + status: UserEventType.VALIDATION_EMAIL, + validation_type: VALIDATION_UTILISATEUR.MANUAL, + granted_by: grantedBy, + }) + } status.push({ date: new Date(), - reason: "validation de l'email à la création", - status: UserEventType.VALIDATION_EMAIL, + reason: "creation de l'utilisateur", + status: UserEventType.ACTIF, validation_type: VALIDATION_UTILISATEUR.MANUAL, granted_by: grantedBy, }) + const now = new Date() + const userFields: IUserWithAccount = { + _id: id, + email: formatedEmail, + first_name, + last_name, + phone: phone ?? "", + last_action_date: last_action_date ?? new Date(), + origin, + status, + createdAt: now, + updatedAt: now, + } + await getDbCollection("userswithaccounts").insertOne(userFields) + user = userFields } - status.push({ - date: new Date(), - reason: "creation de l'utilisateur", - status: UserEventType.ACTIF, - validation_type: VALIDATION_UTILISATEUR.MANUAL, - granted_by: grantedBy, - }) - const userFields: Omit = { - _id: id, - email: formatedEmail, - first_name, - last_name, - phone: phone ?? "", - last_action_date: last_action_date ?? new Date(), - origin, - status, - } - user = (await UserWithAccount.create(userFields)).toObject() return user } -export const validateUserWithAccountEmail = async (id: string): Promise => { - const userOpt = await UserWithAccount.findOne({ _id: id }).lean() +export const validateUserWithAccountEmail = async (id: IUserWithAccount["_id"]): Promise => { + const userOpt = await getDbCollection("userswithaccounts").findOne({ _id: id }) if (!userOpt) { throw Boom.internal(`utilisateur avec id=${id} non trouvé`) } @@ -67,10 +71,14 @@ export const validateUserWithAccountEmail = async (id: string): Promise => UserWithAccount.findOne({ email: email.toLocaleLowerCase() }).lean() +export const getUserWithAccountByEmail = async (email: string): Promise => + getDbCollection("userswithaccounts").findOne({ email: email.toLocaleLowerCase() }) export const emailHasActiveRole = async (email: string): Promise => { const userOpt = await getUserWithAccountByEmail(email) if (!userOpt) return false - const roles = await RoleManagement.find({ user_id: userOpt._id }).lean() + const roles = await getDbCollection("rolemanagements").find({ user_id: userOpt._id }).toArray() const activeStatus = [AccessStatus.GRANTED, AccessStatus.AWAITING_VALIDATION] const activeRoles = roles.filter((role) => { const roleStatus = getLastStatusEvent(role.status)?.status diff --git a/server/tests/integration/common/model.test.ts b/server/tests/integration/common/model.test.ts index 2c071aa148..7d8758ccb7 100644 --- a/server/tests/integration/common/model.test.ts +++ b/server/tests/integration/common/model.test.ts @@ -1,11 +1,7 @@ -import path from "path" - -import { describe, it, expect } from "vitest" - -import __dirname from "@/common/dirname" -import { createMongoDBIndexes } from "@/common/model" -import { mongooseInstance } from "@/common/mongodb" import { useMongo } from "@tests/utils/mongo.utils" +import { describe, expect, it } from "vitest" + +import { createIndexes } from "../../../src/common/utils/mongodbUtils" describe("createMongoDBIndexes", () => { useMongo() @@ -13,7 +9,7 @@ describe("createMongoDBIndexes", () => { it( "should create indexes for all models", async () => { - await expect(createMongoDBIndexes()).resolves.toBeUndefined() + await expect(createIndexes()).resolves.toBeUndefined() }, { timeout: 20_000 } ) @@ -21,13 +17,7 @@ describe("createMongoDBIndexes", () => { it( "should load all schemas", async () => { - const names = mongooseInstance.modelNames() - - // Load all schemas found in our application - await import(path.join(__dirname(import.meta.url), "..", "..", "..", "src", "commands")) - - // If this test fail, make sure the schema is imported in @/common/model/index - expect(names).toEqual(mongooseInstance.modelNames()) + // TODO }, { timeout: 20_000 } ) diff --git a/server/tests/integration/common/users.test.ts b/server/tests/integration/common/users.test.ts deleted file mode 100644 index 9d2c096cd9..0000000000 --- a/server/tests/integration/common/users.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import assert from "assert" - -import { EApplicantRole } from "shared/constants/rdva" -import { describe, it } from "vitest" - -import { useMongo } from "@tests/utils/mongo.utils" - -import { User } from "../../../src/common/model/index" -import { createUser } from "../../../src/services/user.service" - -const userTest = { lastname: "lastname", firstname: "firstname" } - -describe("users", () => { - useMongo() - - it("Permet de créer un utilisateur", async () => { - const created = await createUser(userTest) - assert.strictEqual(created.firstname, "firstname") - - const found = await User.findOne({ firstname: "firstname" }) - assert.strictEqual(found?.firstname, "firstname") - }) - - it("Permet de créer un utilisateur avec le role d'administrateur", async () => { - const user = await createUser({ role: EApplicantRole.ADMINISTRATOR, ...userTest }) - const found = await User.findOne({ firstname: "firstname", role: EApplicantRole.ADMINISTRATOR }) - - assert.strictEqual(user.role, EApplicantRole.ADMINISTRATOR) - assert.strictEqual(found?.role, EApplicantRole.ADMINISTRATOR) - }) - - it("Permet de créer un utilisateur avec le role de candidat", async () => { - const user = await createUser({ role: EApplicantRole.CANDIDAT, ...userTest }) - const found = await User.findOne({ firstname: "firstname", role: EApplicantRole.CANDIDAT }) - - assert.strictEqual(user.role, EApplicantRole.CANDIDAT) - assert.strictEqual(found?.role, EApplicantRole.CANDIDAT) - }) - - it("Permet de créer un utilisateur avec le role de cfa", async () => { - const user = await createUser({ role: EApplicantRole.CFA, ...userTest }) - const found = await User.findOne({ firstname: "firstname", role: EApplicantRole.CFA }) - - assert.strictEqual(user.role, EApplicantRole.CFA) - assert.strictEqual(found?.role, EApplicantRole.CFA) - }) -}) diff --git a/server/tests/integration/http/formationRegionV1.test.ts b/server/tests/integration/http/formationRegionV1.test.ts index 3822e284b9..3b06bc8e89 100644 --- a/server/tests/integration/http/formationRegionV1.test.ts +++ b/server/tests/integration/http/formationRegionV1.test.ts @@ -1,7 +1,6 @@ -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" // Skip from CI (ES is not populated correctly) describe.skipIf(process.env.CI)("formationRegionV1", () => { @@ -17,6 +16,7 @@ describe.skipIf(process.env.CI)("formationRegionV1", () => { it("Vérifie que la recherche avec Rome et region répond avec des résultats", async () => { const res = await httpClient().inject({ method: "GET", path: "/api/V1/formationsParRegion?romes=F1603,I1308®ion=11&caller=a" }) + console.log(res) expect(res.statusCode).toBe(200) expect(JSON.parse(res.body).results).not.toHaveLength(0) }) @@ -109,7 +109,7 @@ describe.skipIf(process.env.CI)("formationRegionV1", () => { const res = await httpClient().inject({ method: "GET", path: "/api/V1/formationsParRegion?romes=F1603,I1308&radius=0&longitude=180&latitude=90&diploma=lba,lbc" }) expect(res.statusCode).toBe(400) - expect(JSON.parse(res.body).error).toEqual("wrong_parameters") - expect(JSON.parse(res.body).error_messages).toContain("diploma : Optional diploma argument used with wrong value") + expect(JSON.parse(res.body).error).toEqual("Bad Request") + expect(JSON.parse(res.body).message).toContain("querystring.diploma: Invalid enum value.") }) }) diff --git a/server/tests/integration/http/formationV1.test.ts b/server/tests/integration/http/formationV1.test.ts index d1b188a01b..a9b6cd9109 100644 --- a/server/tests/integration/http/formationV1.test.ts +++ b/server/tests/integration/http/formationV1.test.ts @@ -1,11 +1,8 @@ import assert from "assert" -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" - -import __filename from "../../../src/common/filename" +import { describe, expect, it } from "vitest" describe("formationV1", () => { useMongo() diff --git a/server/tests/integration/http/healthcheckRoutes.test.ts b/server/tests/integration/http/healthcheckRoutes.test.ts index 4b91c02d49..acced25cc3 100644 --- a/server/tests/integration/http/healthcheckRoutes.test.ts +++ b/server/tests/integration/http/healthcheckRoutes.test.ts @@ -1,7 +1,8 @@ -import { describe, it, expect } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" + +import config from "../../../src/config" describe("healthcheckRoutes", () => { useMongo() @@ -11,10 +12,10 @@ describe("healthcheckRoutes", () => { expect(response.statusCode).toBe(200) expect(JSON.parse(response.body)).toEqual({ + name: "La bonne alternance", + version: config.version, env: "local", - healthcheck: { - mongodb: true, - }, + mongo: true, }) }) }) diff --git a/server/tests/integration/http/jobEtFormationV1.test.ts b/server/tests/integration/http/jobEtFormationV1.test.ts index 417521122b..9766024cf9 100644 --- a/server/tests/integration/http/jobEtFormationV1.test.ts +++ b/server/tests/integration/http/jobEtFormationV1.test.ts @@ -1,9 +1,8 @@ import assert from "assert" -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" describe("jobEtFormationV1", () => { useMongo() diff --git a/server/tests/integration/http/jobV1.test.ts b/server/tests/integration/http/jobV1.test.ts index 70be9fe197..8bfa49c8d3 100644 --- a/server/tests/integration/http/jobV1.test.ts +++ b/server/tests/integration/http/jobV1.test.ts @@ -1,9 +1,8 @@ import assert from "assert" -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" describe.skip("jobV1", () => { useMongo() diff --git a/server/tests/integration/http/partnersRoutes.test.ts b/server/tests/integration/http/partnersRoutes.test.ts index 05388218d5..f482fbb30c 100644 --- a/server/tests/integration/http/partnersRoutes.test.ts +++ b/server/tests/integration/http/partnersRoutes.test.ts @@ -1,9 +1,8 @@ import assert from "assert" -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" describe("partnersRoutes", () => { useMongo() diff --git a/server/tests/integration/http/rolesRoutes.test.ts b/server/tests/integration/http/rolesRoutes.test.ts index d45b6971a1..44015d4028 100644 --- a/server/tests/integration/http/rolesRoutes.test.ts +++ b/server/tests/integration/http/rolesRoutes.test.ts @@ -1,10 +1,9 @@ import assert from "assert" -import { describe, expect, it } from "vitest" - import { createAndLogUser } from "@tests/utils/login.utils" import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" describe("rolesRoutes", () => { useMongo() diff --git a/server/tests/integration/http/romesFromCatalogue.test.ts b/server/tests/integration/http/romesFromCatalogue.test.ts index 9768f72ace..0b40e1899b 100644 --- a/server/tests/integration/http/romesFromCatalogue.test.ts +++ b/server/tests/integration/http/romesFromCatalogue.test.ts @@ -1,9 +1,8 @@ import assert from "assert" -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import { describe, expect, it } from "vitest" describe.skip("romesFromCatalogue", () => { useMongo() diff --git a/server/tests/integration/http/version.test.ts b/server/tests/integration/http/version.test.ts index 5191869637..e2bb633a34 100644 --- a/server/tests/integration/http/version.test.ts +++ b/server/tests/integration/http/version.test.ts @@ -1,10 +1,9 @@ import assert from "assert" -import isSemver from "is-semver" -import { describe, expect, it } from "vitest" - import { useMongo } from "@tests/utils/mongo.utils" import { useServer } from "@tests/utils/server.utils" +import isSemver from "is-semver" +import { describe, expect, it } from "vitest" describe("version", () => { useMongo() diff --git a/server/tests/unit/formation.test.ts b/server/tests/unit/formation.test.ts index c2ae4d6f4d..e92580050b 100644 --- a/server/tests/unit/formation.test.ts +++ b/server/tests/unit/formation.test.ts @@ -2,25 +2,24 @@ import assert from "assert" import { describe, it } from "vitest" -import { FormationCatalogue } from "@/common/model" - import { deduplicateFormations } from "../../src/services/formation.service" describe("formation", () => { const sampleFormation1 = [ - new FormationCatalogue({ nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }), - new FormationCatalogue({ nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }), - new FormationCatalogue({ nom: "a2", intitule: "b2", etablissement_formateur_siret: "c2", diplome: "d2", code_postal: "e2" }), - new FormationCatalogue({ nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }), + { nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }, + { nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }, + { nom: "a2", intitule: "b2", etablissement_formateur_siret: "c2", diplome: "d2", code_postal: "e2" }, + { nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }, ] const sampleFormation2 = [ - new FormationCatalogue({ nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }), - new FormationCatalogue({ nom: "a2", intitule: "b2", etablissement_formateur_siret: "c2", diplome: "d2", code_postal: "e2" }), - new FormationCatalogue({ nom: "a3", intitule: "b3", etablissement_formateur_siret: "c3", diplome: "d3", code_postal: "e3" }), + { nom: "a1", intitule: "b1", etablissement_formateur_siret: "c1", diplome: "d1", code_postal: "e1" }, + { nom: "a2", intitule: "b2", etablissement_formateur_siret: "c2", diplome: "d2", code_postal: "e2" }, + { nom: "a3", intitule: "b3", etablissement_formateur_siret: "c3", diplome: "d3", code_postal: "e3" }, ] it("Détecte les doublons et retourne les items sans doublon ", () => { + // @ts-ignore const deduplicatedList = deduplicateFormations(sampleFormation1) assert.strictEqual(deduplicatedList.length, 2) assert.strictEqual(deduplicatedList[0].nom, "a1") @@ -28,6 +27,7 @@ describe("formation", () => { }) it("Retourne tous les items si pas de doublons ", () => { + // @ts-ignore const deduplicatedList = deduplicateFormations(sampleFormation2) assert.strictEqual(deduplicatedList.length, 3) diff --git a/server/tests/unit/security/accessTokenService.test.ts b/server/tests/unit/security/accessTokenService.test.ts index feb7e2604e..488fe1fbf7 100644 --- a/server/tests/unit/security/accessTokenService.test.ts +++ b/server/tests/unit/security/accessTokenService.test.ts @@ -1,11 +1,10 @@ +import { entrepriseStatusEventFactory, roleManagementEventFactory, saveEntrepriseUserTest } from "@tests/utils/user.utils" import { zRoutes } from "shared" import { z } from "shared/helpers/zodWithOpenApi" import { EntrepriseStatus } from "shared/models/entreprise.model" import { AccessStatus } from "shared/models/roleManagement.model" import { describe, expect, it } from "vitest" -import { entrepriseStatusEventFactory, roleManagementEventFactory, saveEntrepriseUserTest } from "@tests/utils/user.utils" - import { IUserWithAccountForAccessToken as IUserWithAccountForAccessToken, SchemaWithSecurity, diff --git a/server/tests/unit/security/authorisationService.test.ts b/server/tests/unit/security/authorisationService.test.ts index 2dc967477d..02a179ec8f 100644 --- a/server/tests/unit/security/authorisationService.test.ts +++ b/server/tests/unit/security/authorisationService.test.ts @@ -1,4 +1,7 @@ +import { useMongo } from "@tests/utils/mongo.utils" +import { saveAdminUserTest, saveCfaUserTest, saveEntrepriseUserTest, saveOpcoUserTest } from "@tests/utils/user.utils" import { FastifyRequest } from "fastify" +import { ObjectId } from "mongodb" import { IUserWithAccount } from "shared/models/userWithAccount.model" import { AuthStrategy, IRouteSchema, WithSecurityScheme } from "shared/routes/common.routes" import { AccessRessouces } from "shared/security/permissions" @@ -6,8 +9,6 @@ import { describe, expect, it } from "vitest" import { AccessUser2, AccessUserCredential, AccessUserToken } from "@/security/authenticationService" import { authorizationMiddleware } from "@/security/authorisationService" -import { useMongo } from "@tests/utils/mongo.utils" -import { saveAdminUserTest, saveCfaUserTest, saveEntrepriseUserTest, saveOpcoUserTest } from "@tests/utils/user.utils" type MockedRequest = Pick const emptyRequest: MockedRequest = { params: {}, query: {} } @@ -62,7 +63,7 @@ const givenATokenUser = (): AccessUserToken => { // } // } -const givenARequest = ({ user, resourceId }: { user: AccessUserToken | AccessUserCredential | AccessUser2; resourceId?: string }) => { +const givenARequest = ({ user, resourceId }: { user: AccessUserToken | AccessUserCredential | AccessUser2; resourceId?: ObjectId }) => { return { ...emptyRequest, user, @@ -110,12 +111,12 @@ describe("authorisationService", async () => { describe.each(everyResourceType)("given an accessed resource of type %s", (resourceType) => { it("should always allow a token user because authorization has been dealt with in the authentication layer", async () => { await expect( - authorizationMiddleware(givenARoute({ authStrategy: "access-token", resourceType }), givenARequest({ user: givenATokenUser(), resourceId: "resourceId" })) + authorizationMiddleware(givenARoute({ authStrategy: "access-token", resourceType }), givenARequest({ user: givenATokenUser(), resourceId: new ObjectId() })) ).resolves.toBe(undefined) }) it("should always allow an admin user", async () => { await expect( - authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType }), givenARequest({ user: givenAnAdminUser(), resourceId: "resourceId" })) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType }), givenARequest({ user: givenAnAdminUser(), resourceId: new ObjectId() })) ).resolves.toBe(undefined) }) }) @@ -123,10 +124,7 @@ describe("authorisationService", async () => { it("an entreprise user should have access to its user", async () => { const user = entrepriseUserA.user await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), - givenARequest({ user: givenACookieUser(user), resourceId: user._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), givenARequest({ user: givenACookieUser(user), resourceId: user._id })) ).resolves.toBe(undefined) }) it("an entreprise user should NOT have access to another user", async () => { @@ -135,26 +133,20 @@ describe("authorisationService", async () => { await expect( authorizationMiddleware( givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), - givenARequest({ user: givenACookieUser(user), resourceId: accessedUser._id.toString() }) + givenARequest({ user: givenACookieUser(user), resourceId: accessedUser._id }) ) ).rejects.toThrow("non autorisé") }) it("a cfa user should have access to its user", async () => { const user = cfaUserA.user await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), - givenARequest({ user: givenACookieUser(user), resourceId: user._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), givenARequest({ user: givenACookieUser(user), resourceId: user._id })) ).resolves.toBe(undefined) }) it("an opco user should have access to its user", async () => { const user = opcoUserA.user await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), - givenARequest({ user: givenACookieUser(user), resourceId: user._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "user" }), givenARequest({ user: givenACookieUser(user), resourceId: user._id })) ).resolves.toBe(undefined) }) }) @@ -163,10 +155,7 @@ describe("authorisationService", async () => { const { user, recruiter } = entrepriseUserA const [job] = recruiter.jobs await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), - givenARequest({ user: givenACookieUser(user), resourceId: job._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), givenARequest({ user: givenACookieUser(user), resourceId: job._id })) ).resolves.toBe(undefined) }) it("an entreprise user should NOT have access to another entreprise's jobs", async () => { @@ -174,20 +163,14 @@ describe("authorisationService", async () => { const { recruiter } = entrepriseUserB const [job] = recruiter.jobs await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), - givenARequest({ user: givenACookieUser(user), resourceId: job._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), givenARequest({ user: givenACookieUser(user), resourceId: job._id })) ).rejects.toThrow("non autorisé") }) it("a cfa user should have access to its jobs", async () => { const { user, recruiter } = cfaUserA const [job] = recruiter.jobs await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), - givenARequest({ user: givenACookieUser(user), resourceId: job._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), givenARequest({ user: givenACookieUser(user), resourceId: job._id })) ).resolves.toBe(undefined) }) it("a cfa user should NOT have access to another cfa's job", async () => { @@ -195,10 +178,7 @@ describe("authorisationService", async () => { const { recruiter } = cfaUserB const [job] = recruiter.jobs await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), - givenARequest({ user: givenACookieUser(user), resourceId: job._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), givenARequest({ user: givenACookieUser(user), resourceId: job._id })) ).rejects.toThrow("non autorisé") }) it("a cfa user should NOT have access to another entreprise job", async () => { @@ -206,10 +186,7 @@ describe("authorisationService", async () => { const { recruiter } = entrepriseUserA const [job] = recruiter.jobs await expect( - authorizationMiddleware( - givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), - givenARequest({ user: givenACookieUser(user), resourceId: job._id.toString() }) - ) + authorizationMiddleware(givenARoute({ authStrategy: "cookie-session", resourceType: "job" }), givenARequest({ user: givenACookieUser(user), resourceId: job._id })) ).rejects.toThrow("non autorisé") }) }) diff --git a/server/tests/utils/globalSetup.ts b/server/tests/utils/globalSetup.ts index c9f222154a..a1625ab056 100644 --- a/server/tests/utils/globalSetup.ts +++ b/server/tests/utils/globalSetup.ts @@ -5,7 +5,11 @@ export default async () => { return async () => { config({ path: "./server/.env.test" }) - const client = new MongoClient(process.env.LBA_MONGODB_URI?.replace("VITEST_POOL_ID", "") ?? "") + const client = new MongoClient(process.env.LBA_MONGODB_URI?.replace("VITEST_POOL_ID", "") ?? "", { + connectTimeoutMS: 1_000, + socketTimeoutMS: 1_000, + serverSelectionTimeoutMS: 1_000, + }) try { if (process.env.CI) { return diff --git a/server/tests/utils/mongo.utils.ts b/server/tests/utils/mongo.utils.ts index cca602cd7c..38fdab6ab3 100644 --- a/server/tests/utils/mongo.utils.ts +++ b/server/tests/utils/mongo.utils.ts @@ -1,44 +1,28 @@ -import mongoose from "mongoose" +import { modelDescriptors } from "shared/models/models" import { afterAll, beforeAll, beforeEach } from "vitest" -import { connectToMongo } from "@/common/mongodb" +import { clearAllCollections, closeMongodbConnection, configureDbSchemaValidation, connectToMongodb, createIndexes } from "@/common/utils/mongodbUtils" import config from "@/config" -import { createMongoDBIndexes } from "../../src/common/model" - export const startAndConnectMongodb = async () => { const workerId = `${process.env.VITEST_POOL_ID}-${process.env.VITEST_WORKER_ID}` - await connectToMongo(config.mongodb.uri.replace("VITEST_POOL_ID", workerId)) - await createMongoDBIndexes() + await connectToMongodb(config.mongodb.uri.replace("VITEST_POOL_ID", workerId)) + await Promise.all([createIndexes(), configureDbSchemaValidation(modelDescriptors)]) } export const stopMongodb = async () => { - try { - await mongoose.disconnect() - } catch (err) { - // no-op - } + await closeMongodbConnection() } type MockData = () => Promise // beforeAll are ran in parallel, we need to wait for clearDb to be done before mocking data export const useMongo = (mock: MockData | null = null, step: "beforeAll" | "beforeEach" = "beforeEach") => { - const clearDb = async () => { - const collections = mongoose.connection.collections - - await Promise.all( - Object.values(collections).map(async (collection) => { - await collection.deleteMany({}) - }) - ) - } - beforeAll(async () => { await startAndConnectMongodb() if (step === "beforeAll") { - await clearDb() + await clearAllCollections() await mock?.() } }) @@ -49,7 +33,7 @@ export const useMongo = (mock: MockData | null = null, step: "beforeAll" | "befo if (step === "beforeEach") { beforeEach(async () => { - await clearDb() + await clearAllCollections() await mock?.() }) } diff --git a/server/tests/utils/user.utils.ts b/server/tests/utils/user.utils.ts index 25a13eb4ad..f66cfded29 100644 --- a/server/tests/utils/user.utils.ts +++ b/server/tests/utils/user.utils.ts @@ -1,3 +1,4 @@ +import { ObjectId } from "mongodb" import { OPCOS, RECRUITER_STATUS, VALIDATION_UTILISATEUR } from "shared/constants/recruteur" import { extensions } from "shared/helpers/zodHelpers/zodPrimitives" import { IApplication, ICredential, IEmailBlacklist, IJob, IRecruiter, JOB_STATUS, ZApplication, ZCredential, ZEmailBlacklist } from "shared/models" @@ -9,8 +10,7 @@ import { IUserWithAccount, UserEventType, ZUserWithAccount } from "shared/models import { ZodObject, ZodString, ZodTypeAny } from "zod" import { Fixture, Generator } from "zod-fixture" -import { Application, Cfa, Credential, EmailBlacklist, Entreprise, Recruiter, RoleManagement, UserWithAccount } from "@/common/model" -import { ObjectId } from "@/common/mongodb" +import { getDbCollection } from "@/common/utils/mongodbUtils" let seed = 0 function getFixture() { @@ -52,17 +52,17 @@ function getFixture() { ]) } -export const saveDbEntity = async (schema: ZodTypeAny, dbModel: (item: T) => { save: () => Promise } & T, data: Partial) => { - const u = dbModel({ +export const saveDbEntity = async (schema: ZodTypeAny, saveEntity: (item: T) => Promise, data: Partial) => { + const entity = { ...getFixture().fromSchema(schema), ...data, - }) - await u.save() - return u + } + await saveEntity(entity) + return entity } export const saveUserWithAccount = async (data: Partial = {}) => { - return saveDbEntity(ZUserWithAccount, (item) => new UserWithAccount(item), data) + return saveDbEntity(ZUserWithAccount, (item) => getDbCollection("userswithaccounts").insertOne(item), data) } export const saveRoleManagement = async (data: Partial = {}) => { const role: IRoleManagement = { @@ -76,7 +76,7 @@ export const saveRoleManagement = async (data: Partial = {}) => user_id: new ObjectId(), ...data, } - await new RoleManagement(role).save() + await getDbCollection("rolemanagements").insertOne(role) return role } @@ -97,7 +97,7 @@ export const roleManagementEventFactory = ({ } export const saveEntreprise = async (data: Partial = {}) => { - return saveDbEntity(ZEntreprise, (item) => new Entreprise(item), data) + return saveDbEntity(ZEntreprise, (item) => getDbCollection("entreprises").insertOne(item), data) } export const entrepriseStatusEventFactory = (props: Partial = {}): IEntrepriseStatusEvent => { @@ -111,7 +111,7 @@ export const entrepriseStatusEventFactory = (props: Partial = {}) => { - return saveDbEntity(zCFA, (item) => new Cfa(item), data) + return saveDbEntity(zCFA, (item) => getDbCollection("cfas").insertOne(item), data) } export const jobFactory = (props: Partial = {}) => { @@ -119,7 +119,7 @@ export const jobFactory = (props: Partial = {}) => { _id: new ObjectId(), rome_label: "rome_label", rome_appellation_label: "rome_appellation_label", - job_level_label: "job_level_label", + job_level_label: "BTS, DEUST, autres formations niveau (Bac+2)", job_start_date: new Date(), job_description: "job_description", job_employer_description: "job_employer_description", @@ -139,23 +139,23 @@ export const jobFactory = (props: Partial = {}) => { is_disabled_elligible: false, job_count: 1, job_duration: 6, - job_rythm: "job_rythm", + job_rythm: "Indifférent", custom_address: "custom_address", custom_geo_coordinates: "custom_geo_coordinates", stats_detail_view: 0, stats_search_view: 0, - managed_by: new ObjectId(), + managed_by: new ObjectId().toString(), ...props, } return job } export async function createCredentialTest(data: Partial) { - const u = new Credential({ + const u: ICredential = { ...getFixture().fromSchema(ZCredential), ...data, - }) - await u.save() + } + await getDbCollection("credentials").insertOne(u) return u } @@ -193,26 +193,25 @@ export async function saveRecruiter(data: Partial) { establishment_creation_date: new Date(), ...data, } - const u = new Recruiter(recruiter) - await u.save() - return u + await getDbCollection("recruiters").insertOne(recruiter) + return recruiter } export async function createApplicationTest(data: Partial) { - const u = new Application({ + const u: IApplication = { ...getFixture().fromSchema(ZApplication), ...data, - }) - await u.save() + } + await getDbCollection("applications").insertOne(u) return u } export async function createEmailBlacklistTest(data: Partial) { - const u = new EmailBlacklist({ + const u = { ...getFixture().fromSchema(ZEmailBlacklist), ...data, - }) - await u.save() + } + await getDbCollection("emailblacklists").insertOne(u) return u } @@ -221,7 +220,7 @@ export const saveAdminUserTest = async (userProps: Partial = { const role = await saveRoleManagement({ user_id: user._id, authorized_type: AccessEntityType.ADMIN, - authorized_id: undefined, + authorized_id: new ObjectId().toString(), status: [roleManagementEventFactory()], }) return { user, role } @@ -245,7 +244,7 @@ export const saveEntrepriseUserTest = async (userProps: Partial = {}) status: RECRUITER_STATUS.ACTIF, jobs: [ jobFactory({ - managed_by: user._id, + managed_by: user._id.toString(), }), ], }) diff --git a/shared/constants/appointment.ts b/shared/constants/appointment.ts index 088cd9b463..9fef4c7b43 100644 --- a/shared/constants/appointment.ts +++ b/shared/constants/appointment.ts @@ -2,3 +2,9 @@ export enum AppointmentUserType { PARENT = "parent", ETUDIENT = "etudiant", } + +export enum mailType { + CANDIDAT_HAVE_YOU_BEEN_CONTACTED = "CANDIDAT_HAVE_YOU_BEEN_CONTACTED", + CFA_REMINDER_RESEND_APPOINTMENT = "CFA_REMINDER_RESEND_APPOINTMENT", + CANDIDAT_APPOINTMENT = "CANDIDAT_APPOINTMENT", +} diff --git a/shared/constants/referers.ts b/shared/constants/referers.ts index 8cf130f6ff..47f7ede833 100644 --- a/shared/constants/referers.ts +++ b/shared/constants/referers.ts @@ -1,3 +1,9 @@ +export type ReferrerObject = { + code: number + name: string + full_name: string + url: string +} // Referrer configurations export const referrers = { PARCOURSUP: { diff --git a/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap b/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap index 235cbc829b..8e06a5cbb0 100644 --- a/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap +++ b/shared/helpers/openapi/__snapshots__/generateOpenapi.test.ts.snap @@ -106,7 +106,10 @@ exports[`generateOpenApiSchema > should generate proper schema 1`] = ` "company_naf": { "description": "La valeur associée au code NAF de l'entreprise. Fournie par La bonne alternance. ", "example": "Boulangerie et boulangerie-pâtisserie", - "type": "string", + "type": [ + "string", + "null", + ], }, "company_name": { "description": "Le nom de la société. Fourni par La bonne alternance. ", @@ -154,7 +157,10 @@ exports[`generateOpenApiSchema > should generate proper schema 1`] = ` "job_title": { "description": "Le titre de l'offre La bonne alternance Recruteur pour laquelle la candidature est envoyée. Seulement si le type de la société (company_type) est offres_emploi_lba . La valeur est fournie par La bonne alternance. ", "example": "Téléconseil, vente à distance", - "type": "string", + "type": [ + "string", + "null", + ], }, "message": { "description": "Un message du candidat vers le recruteur. Ce champ peut contenir la lettre de motivation du candidat.", @@ -186,8 +192,6 @@ exports[`generateOpenApiSchema > should generate proper schema 1`] = ` "applicant_phone", "company_siret", "company_name", - "company_naf", - "job_title", "applicant_file_name", "applicant_file_content", "company_type", @@ -862,6 +866,10 @@ exports[`generateOpenApiSchema > should generate proper schema 1`] = ` }, "managed_by": { "description": "Id de l'utilisateur gérant l'offre", + "type": [ + "string", + "null", + ], }, "relance_mail_sent": { "description": "Statut de l'envoi du mail de relance avant expiration", @@ -2776,6 +2784,10 @@ exports[`generateOpenApiSchema > should generate proper schema 1`] = ` }, "managed_by": { "description": "Id de l'utilisateur gestionnaire", + "type": [ + "string", + "null", + ], }, "naf_code": { "description": "Code NAF de l'établissement", @@ -8773,7 +8785,6 @@ Limite : 5 appel(s) / 1 seconde(s) "content": { "application/json": { "schema": { - "additionalProperties": false, "properties": { "lbaCompanies": { "items": { @@ -9270,7 +9281,6 @@ Limite : 5 appel(s) / 1 seconde(s) "content": { "application/json": { "schema": { - "additionalProperties": false, "properties": { "peJobs": { "items": { @@ -9395,7 +9405,6 @@ Limite : 5 appel(s) / 1 seconde(s) "content": { "application/json": { "schema": { - "additionalProperties": false, "properties": { "matchas": { "items": { diff --git a/shared/models/anonymizedApplications.model.ts b/shared/models/anonymizedApplications.model.ts deleted file mode 100644 index 0981ac7e04..0000000000 --- a/shared/models/anonymizedApplications.model.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LBA_ITEM_TYPE, allLbaItemType } from "../constants/lbaitem" -import { extensions } from "../helpers/zodHelpers/zodPrimitives" -import { z } from "../helpers/zodWithOpenApi" - -import { zObjectId } from "./common" - -export const ZAnonymizedApplication = z - .object({ - _id: zObjectId, - company_recruitment_intention: z.string().nullable().describe("L'intention de la société vis à vis du candidat"), - company_feedback_date: z.date().nullable().describe("Date d'intention/avis donnée"), - company_siret: extensions.siret.describe('Le siret de l\'entreprise. Fourni par La bonne alternance. Example: "00004993900000"'), - company_naf: z.string().describe('La valeur associée au code NAF de l\'entreprise. Fournie par La bonne alternance. Example: "Boulangerie et boulangerie-pâtisserie"'), - job_origin: z - .enum([allLbaItemType[0], ...allLbaItemType.slice(1)]) - .nullable() - .describe("Le type de société selon la nomenclature La bonne alternance. Fourni par La bonne alternance"), - job_id: z - .string() - .nullable() - .describe( - `L'identifiant de l'offre La bonne alternance Recruteur pour laquelle la candidature est envoyée. Seulement si le type de la société (company_type) est ${LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA}. La valeur est fournie par La bonne alternance. Example: "...59c24c059b..."` - ), - caller: z.string().nullable().describe("L'identification de la source d'émission de la candidature (pour widget et api)"), - created_at: z.date().nullable().describe("La date création de la demande"), - }) - .strict() - .describe("Anonymized Application") - -export type IAnonymizedApplication = z.output diff --git a/shared/models/anonymizedUsers.model.ts b/shared/models/anonymizedUsers.model.ts deleted file mode 100644 index 76a607dfb0..0000000000 --- a/shared/models/anonymizedUsers.model.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { z } from "../helpers/zodWithOpenApi" - -import { zObjectId } from "./common" - -export const zAnonymizedUser = z - .object({ - _id: zObjectId, - role: z.string(), - type: z.string(), - last_action_date: z.date(), - }) - .strict() - -export type IAnonymizedUser = z.output diff --git a/shared/models/apicalls.model.ts b/shared/models/apicalls.model.ts index b2a7022d4f..01f01b598a 100644 --- a/shared/models/apicalls.model.ts +++ b/shared/models/apicalls.model.ts @@ -1,6 +1,8 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "apicalls" as const export const ZApiCall = z .object({ @@ -15,7 +17,10 @@ export const ZApiCall = z }) .strict() -export const ZApiCallNew = ZApiCall.omit({ - _id: true, - created_at: true, -}) +export type IApiCall = z.output + +export default { + zod: ZApiCall, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/applications.model.ts b/shared/models/applications.model.ts index 576249770e..c40f71d32a 100644 --- a/shared/models/applications.model.ts +++ b/shared/models/applications.model.ts @@ -4,7 +4,9 @@ import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" import { zCallerParam } from "../routes/_params" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "applications" as const export const ZApplication = z .object({ @@ -44,9 +46,9 @@ export const ZApplication = z description: "Un message du candidat vers le recruteur. Ce champ peut contenir la lettre de motivation du candidat.", example: "Madame, monsieur...", }), - company_recruitment_intention: z.string().nullable().describe("L'intention de la société vis à vis du candidat"), - company_feedback: z.string().nullable().describe("L'avis donné par la société"), - company_feedback_date: z.date().nullable().describe("Date d'intention/avis donnée"), + company_recruitment_intention: z.string().nullish().describe("L'intention de la société vis à vis du candidat"), + company_feedback: z.string().nullish().describe("L'avis donné par la société"), + company_feedback_date: z.date().nullish().describe("Date d'intention/avis donnée"), company_siret: extensions.siret.openapi({ description: "Le siret de l'entreprise. Fourni par La bonne alternance. ", example: "00004993900000", @@ -60,7 +62,7 @@ export const ZApplication = z description: "Le nom de la société. Fourni par La bonne alternance. ", example: "Au bon pain d'antan", }), - company_naf: z.string().openapi({ + company_naf: z.string().nullish().openapi({ description: "La valeur associée au code NAF de l'entreprise. Fournie par La bonne alternance. ", example: "Boulangerie et boulangerie-pâtisserie", }), @@ -75,20 +77,23 @@ export const ZApplication = z description: "Le type de société selon la nomenclature La bonne alternance. Fourni par La bonne alternance.", example: LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA, }), - job_title: z.string().openapi({ - description: `Le titre de l'offre La bonne alternance Recruteur pour laquelle la candidature est envoyée. Seulement si le type de la société (company_type) est ${LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA} . La valeur est fournie par La bonne alternance. `, - example: "Téléconseil, vente à distance", - }), + job_title: z + .string() + .nullish() + .openapi({ + description: `Le titre de l'offre La bonne alternance Recruteur pour laquelle la candidature est envoyée. Seulement si le type de la société (company_type) est ${LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA} . La valeur est fournie par La bonne alternance. `, + example: "Téléconseil, vente à distance", + }), job_id: z .string() - .nullable() + .nullish() .openapi({ description: `L'identifiant de l'offre La bonne alternance Recruteur pour laquelle la candidature est envoyée. Seulement si le type de la société (company_type) est ${LBA_ITEM_TYPE.OFFRES_EMPLOI_LBA} . La valeur est fournie par La bonne alternance. `, example: "...59c24c059b...", }), - to_applicant_message_id: z.string().nullable().describe("Identifiant chez le transporteur du mail envoyé au candidat"), - to_company_message_id: z.string().nullable().describe("Identifiant chez le transporteur du mail envoyé à l'entreprise"), - caller: z.string().nullish().describe("L'identification de la source d'émission de la candidature"), + to_applicant_message_id: z.string().nullish().describe("Identifiant chez le transporteur du mail envoyé au candidat"), + to_company_message_id: z.string().nullish().describe("Identifiant chez le transporteur du mail envoyé à l'entreprise"), + caller: z.string().nullish().describe("L'identification de la source d'émission de la candidature (pour widget et api)"), created_at: z.date().nullable().describe("La date création de la demande"), last_update_at: z.date().nullable().describe("Date de dernières mise à jour"), }) @@ -220,3 +225,9 @@ export type INewApplicationV2 = z.output export type INewApplication = z.output export type IApplication = z.output + +export default { + zod: ZApplication, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/appointments.model.ts b/shared/models/appointments.model.ts index b83e790602..26ee2fbf2c 100644 --- a/shared/models/appointments.model.ts +++ b/shared/models/appointments.model.ts @@ -3,9 +3,11 @@ import { Jsonify } from "type-fest" import { AppointmentUserType } from "../constants/appointment" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" import { enumToZod } from "./enumToZod" +const collectionName = "appointments" as const + export const enum EReasonsKey { MODALITE = "modalite", CONTENU = "contenu", @@ -22,6 +24,7 @@ export const enum EReasonsKey { } export const EREASONS = Object.values(["modalite", "contenu", "porte", "frais", "place", "horaire", "plus", "accompagnement", "lieu", "suivi", "autre", "debouche"]) +export type EReason = NonNullable[0] export const ZMailing = z .object({ @@ -34,10 +37,12 @@ export const ZMailing = z .strict() .openapi("Mailing") +export type IMailing = z.output + export const ZAppointment = z .object({ _id: zObjectId, - applicant_id: zObjectId, + applicant_id: z.string(), cfa_intention_to_applicant: z.string().nullish(), cfa_message_to_applicant_date: z.date().nullish(), cfa_message_to_applicant: z.string().nullish(), @@ -47,8 +52,8 @@ export const ZAppointment = z cfa_formateur_siret: z.string().nullish(), appointment_origin: z.string(), cfa_read_appointment_details_date: z.date().nullish(), - to_applicant_mails: z.array(ZMailing).nullable(), - to_cfa_mails: z.array(ZMailing), + to_applicant_mails: z.array(ZMailing).nullish(), + to_cfa_mails: z.array(ZMailing).nullish(), cle_ministere_educatif: z.string(), created_at: z.date().default(() => new Date()), cfa_recipient_email: z.string(), @@ -60,5 +65,8 @@ export const ZAppointment = z export type IAppointment = z.output export type IAppointmentJson = Jsonify> -export type IMailing = z.output -export type EReason = NonNullable[0] +export default { + zod: ZAppointment, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/cfa.model.ts b/shared/models/cfa.model.ts index 6f487f62bc..775d91811d 100644 --- a/shared/models/cfa.model.ts +++ b/shared/models/cfa.model.ts @@ -3,7 +3,9 @@ import { Jsonify } from "type-fest" import { z } from "../helpers/zodWithOpenApi" import { ZGlobalAddress } from "./address.model" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "cfas" as const export const zCFA = z .object({ @@ -22,3 +24,9 @@ export const zCFA = z export type ICFA = z.output export type ICFAJson = Jsonify> + +export default { + zod: zCFA, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/common.ts b/shared/models/common.ts index 80b7e9a0a1..aa4e66b3ed 100644 --- a/shared/models/common.ts +++ b/shared/models/common.ts @@ -1,19 +1,10 @@ -import BSON, { type ObjectId } from "bson" -import type { IndexOptions, IndexSpecification } from "mongodb" -import { ZodType, z } from "zod" +import { CreateIndexesOptions, IndexSpecification } from "mongodb" +import { ZodType } from "zod" -export type CollectionName = "users" | "jobs" | "organisations" | "persons" | "events" | "sessions" | "documents" | "documentContents" | "mailingLists" - -export interface IModelDescriptor { - zod: ZodType - indexes: [IndexSpecification, IndexOptions][] +export interface IModelDescriptor { + zod: LocalZodType + indexes: [IndexSpecification, CreateIndexesOptions][] collectionName: CollectionName } -export const zObjectId = z - .custom((v) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return BSON.ObjectID.isValid(v as any) - }) - .transform((v) => new BSON.ObjectID(v)) - .describe("Identifiant unique") +export { zObjectId } from "zod-mongodb-schema" diff --git a/shared/models/credentials.model.ts b/shared/models/credentials.model.ts index dad629c055..6df0860109 100644 --- a/shared/models/credentials.model.ts +++ b/shared/models/credentials.model.ts @@ -1,6 +1,8 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "credentials" as const export const ZCredential = z .object({ @@ -18,3 +20,9 @@ export const ZCredential = z .strict() export type ICredential = z.output + +export default { + zod: ZCredential, + indexes: [[{ api_key: 1 }, { unique: true }]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/customEmailETFA.model.ts b/shared/models/customEmailETFA.model.ts index f4f78091db..4fb98ae8fd 100644 --- a/shared/models/customEmailETFA.model.ts +++ b/shared/models/customEmailETFA.model.ts @@ -1,6 +1,8 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "customemailetfas" as const export const ZCustomEmailETFA = z .object({ @@ -11,3 +13,9 @@ export const ZCustomEmailETFA = z .strict() export type ICustomEmailETFA = z.output + +export default { + zod: ZCustomEmailETFA, + indexes: [[{ cle_ministere_educatif: 1 }, {}]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/metiers.model.ts b/shared/models/diplomesMetiers.model.ts similarity index 61% rename from shared/models/metiers.model.ts rename to shared/models/diplomesMetiers.model.ts index 52ad56ee70..14958a63c2 100644 --- a/shared/models/metiers.model.ts +++ b/shared/models/diplomesMetiers.model.ts @@ -1,6 +1,6 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" export const ZRomeWithLabel = z .object({ @@ -91,6 +91,8 @@ export const ZAppellationsRomes = z }) .strict() +const collectionName = "diplomesmetiers" as const + export const ZDiplomesMetiers = z .object({ _id: zObjectId, @@ -103,50 +105,10 @@ export const ZDiplomesMetiers = z }) .strict() -export const ZDiplomesMetiersNew = ZDiplomesMetiers.omit({ _id: true, created_at: true, last_update_at: true }).strict() +export type IDiplomesMetiers = z.output -export const ZDomainesMetiers = z - .object({ - _id: zObjectId.nullish(), - sous_domaine: z.string(), - sous_domaine_sans_accent_computed: z.string(), - domaine: z.string(), - domaine_sans_accent_computed: z.string(), - codes_romes: z.array(z.string()), - intitules_romes: z.array(z.string()), - intitules_romes_sans_accent_computed: z.array(z.string()), - codes_rncps: z.array(z.string()), - intitules_rncps: z.array(z.string()), - intitules_rncps_sans_accent_computed: z.array(z.string()), - mots_clefs: z.string(), - mots_clefs_sans_accent_computed: z.string(), - mots_clefs_specifiques: z.string(), - mots_clefs_specifiques_sans_accent_computed: z.string(), - appellations_romes: z.string(), - appellations_romes_sans_accent_computed: z.string(), - codes_fap: z.array(z.string()), - intitules_fap: z.array(z.string()), - intitules_fap_sans_accent_computed: z.array(z.string()), - sous_domaine_onisep: z.array(z.string()), - sous_domaine_onisep_sans_accent_computed: z.array(z.string()), - couples_appellations_rome_metier: z.array( - z - .object({ - codeRome: z.string(), - intitule: z.string(), - appellation: z.string(), - }) - .strict() - ), - couples_romes_metiers: z.array( - z - .object({ - codeRome: z.string(), - intitule: z.string(), - }) - .strict() - ), - created_at: z.date(), - last_update_at: z.date(), - }) - .strict() +export default { + zod: ZDiplomesMetiers, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/domainesMetiers.model.ts b/shared/models/domainesMetiers.model.ts new file mode 100644 index 0000000000..8e4b8361ba --- /dev/null +++ b/shared/models/domainesMetiers.model.ts @@ -0,0 +1,59 @@ +import { z } from "../helpers/zodWithOpenApi" + +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "domainesmetiers" as const + +export const ZDomainesMetiers = z + .object({ + _id: zObjectId.nullish(), + sous_domaine: z.string(), + sous_domaine_sans_accent_computed: z.string(), + domaine: z.string(), + domaine_sans_accent_computed: z.string(), + codes_romes: z.array(z.string()), + intitules_romes: z.array(z.string()), + intitules_romes_sans_accent_computed: z.array(z.string()), + codes_rncps: z.array(z.string()), + intitules_rncps: z.array(z.string()), + intitules_rncps_sans_accent_computed: z.array(z.string()), + mots_clefs: z.string(), + mots_clefs_sans_accent_computed: z.string(), + mots_clefs_specifiques: z.string(), + mots_clefs_specifiques_sans_accent_computed: z.string(), + appellations_romes: z.string(), + appellations_romes_sans_accent_computed: z.string(), + codes_fap: z.array(z.string()), + intitules_fap: z.array(z.string()), + intitules_fap_sans_accent_computed: z.array(z.string()), + sous_domaine_onisep: z.array(z.string()), + sous_domaine_onisep_sans_accent_computed: z.array(z.string()), + couples_appellations_rome_metier: z.array( + z + .object({ + codeRome: z.string(), + intitule: z.string(), + appellation: z.string(), + }) + .strict() + ), + couples_romes_metiers: z.array( + z + .object({ + codeRome: z.string(), + intitule: z.string(), + }) + .strict() + ), + created_at: z.date(), + last_update_at: z.date(), + }) + .strict() + +export type IDomainesMetiers = z.output + +export default { + zod: ZDomainesMetiers, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/elligibleTraining.model.ts b/shared/models/elligibleTraining.model.ts index 67de022fcc..10c6f0dd45 100644 --- a/shared/models/elligibleTraining.model.ts +++ b/shared/models/elligibleTraining.model.ts @@ -3,9 +3,11 @@ import { Jsonify } from "type-fest" import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" import { ZEtablissement } from "./etablissement.model" +const collectionName = "eligible_trainings_for_appointments" as const + export const ZEligibleTrainingsForAppointmentSchema = z .object({ _id: zObjectId, @@ -40,3 +42,16 @@ export const ZEligibleTrainingsForAppointmentSchema = z export type IEligibleTrainingsForAppointment = z.output export type IEligibleTrainingsForAppointmentJson = Jsonify> + +export default { + zod: ZEligibleTrainingsForAppointmentSchema, + indexes: [ + [{ affelnet_visible: 1 }, {}], + [{ cle_ministere_educatif: 1 }, {}], + [{ parcoursup_id: 1 }, {}], + [{ parcoursup_visible: 1 }, {}], + [{ rco_formation_id: 1 }, {}], + [{ referrers: 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/elligibleTrainingHistory.model.ts b/shared/models/elligibleTrainingHistory.model.ts new file mode 100644 index 0000000000..f929eca390 --- /dev/null +++ b/shared/models/elligibleTrainingHistory.model.ts @@ -0,0 +1,17 @@ +import { IModelDescriptor } from "./common" +import { ZEligibleTrainingsForAppointmentSchema } from "./elligibleTraining.model" + +const collectionName = "eligible_trainings_for_appointments_history" as const + +export default { + zod: ZEligibleTrainingsForAppointmentSchema, + indexes: [ + [{ affelnet_visible: 1 }, {}], + [{ cle_ministere_educatif: 1 }, {}], + [{ parcoursup_id: 1 }, {}], + [{ parcoursup_visible: 1 }, {}], + [{ rco_formation_id: 1 }, {}], + [{ referrers: 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/emailBlacklist.model.ts b/shared/models/emailBlacklist.model.ts index 7d38589c97..d9a55661dc 100644 --- a/shared/models/emailBlacklist.model.ts +++ b/shared/models/emailBlacklist.model.ts @@ -2,7 +2,9 @@ import { Jsonify } from "type-fest" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "emailblacklists" as const export const ZEmailBlacklist = z .object({ @@ -15,3 +17,9 @@ export const ZEmailBlacklist = z export type IEmailBlacklist = z.output export type IEmailBlacklistJson = Jsonify> + +export default { + zod: ZEmailBlacklist, + indexes: [[{ email: 1 }, { unique: true }]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/entreprise.model.ts b/shared/models/entreprise.model.ts index acc976b473..02992c21e4 100644 --- a/shared/models/entreprise.model.ts +++ b/shared/models/entreprise.model.ts @@ -3,7 +3,7 @@ import { Jsonify } from "type-fest" import { z } from "../helpers/zodWithOpenApi" import { ZGlobalAddress } from "./address.model" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" import { enumToZod } from "./enumToZod" import { ZValidationUtilisateur } from "./userWithAccount.model" @@ -26,6 +26,8 @@ export const ZEntrepriseStatusEvent = z export type IEntrepriseStatusEvent = z.output +const collectionName = "entreprises" as const + export const ZEntreprise = z .object({ _id: zObjectId, @@ -46,3 +48,12 @@ export const ZEntreprise = z export type IEntreprise = z.output export type IEntrepriseJson = Jsonify> + +export default { + zod: ZEntreprise, + indexes: [ + [{ siret: 1 }, {}], + [{ "status.status": 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/etablissement.model.ts b/shared/models/etablissement.model.ts index e331d70515..fc994f57b9 100644 --- a/shared/models/etablissement.model.ts +++ b/shared/models/etablissement.model.ts @@ -3,7 +3,9 @@ import { Jsonify } from "type-fest" import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "etablissements" as const export const ZEtablissement = z .object({ @@ -39,3 +41,17 @@ export const ZEtablissement = z export type IEtablissement = z.output export type IEtablissementJson = Jsonify> + +export default { + zod: ZEtablissement, + indexes: [ + [{ formateur_siret: 1 }, {}], + [{ gestionnaire_siret: 1 }, {}], + [{ premium_activation_date: 1 }, {}], + [{ premium_affelnet_activation_date: 1 }, {}], + [{ to_CFA_invite_optout_last_message_id: 1 }, {}], + [{ optout_activation_date: 1 }, {}], + ], + + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/formation.model.ts b/shared/models/formation.model.ts index 6e6d3acba3..a4251dca85 100644 --- a/shared/models/formation.model.ts +++ b/shared/models/formation.model.ts @@ -1,7 +1,7 @@ import { z } from "../helpers/zodWithOpenApi" import { ZPointGeometry } from "./address.model" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" // Define schemas for nested objects const geoCoordSchema = z.string() @@ -87,6 +87,8 @@ const etablissementReferenceSchema = z // Define a schema for a single string or an array of strings const stringOrArraySchema = z.union([z.string(), z.array(z.string())]) +const collectionName = "formationcatalogues" as const + // Define the Zod schema for IFormationCatalogue export const zFormationCatalogueSchema = z .object({ @@ -94,7 +96,7 @@ export const zFormationCatalogueSchema = z cle_ministere_educatif: z.string().nullish(), cfd: z.string(), cfd_specialite: z.string().nullish(), - cfa_outdated: z.boolean().nullish(), + cfd_outdated: z.boolean().nullish(), cfd_date_fermeture: z.date().nullish(), cfd_entree: z.string().nullish(), mef_10_code: z.string().nullish(), @@ -196,3 +198,28 @@ export const zFormationCatalogueSchema = z export const zFormationCatalogueSchemaNew = zFormationCatalogueSchema.omit({ _id: true }) export type IFormationCatalogue = z.output + +export default { + zod: zFormationCatalogueSchema, + indexes: [ + [{ cle_ministere_educatif: 1 }, {}], + [{ cfd: 1 }, {}], + [{ cfd_entree: 1 }, {}], + [{ uai_formation: 1 }, {}], + [{ niveau: 1 }, {}], + [{ rncp_code: 1 }, {}], + [{ rome_codes: 1 }, {}], + [{ parcoursup_id: 1 }, {}], + [{ published: 1 }, {}], + [{ to_update: 1 }, {}], + [{ id_rco_formation: 1 }, {}], + [{ id_formation: 1 }, {}], + [{ id_action: 1 }, {}], + [{ ids_action: 1 }, {}], + [{ id_certifinfo: 1 }, {}], + [{ tags: 1 }, {}], + [{ catalogue_published: 1 }, {}], + [{ lieu_formation_geopoint: "2dsphere" }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/geolocations.model.ts b/shared/models/geolocations.model.ts index 4c52d27a15..e5d96fcb79 100644 --- a/shared/models/geolocations.model.ts +++ b/shared/models/geolocations.model.ts @@ -1,6 +1,8 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "geolocations" as const export const ZGeoLocation = z .object({ @@ -12,4 +14,10 @@ export const ZGeoLocation = z }) .strict() -export const ZGeoLocationNew = ZGeoLocation.omit({ _id: true }).strict() +export type IGeoLocation = z.output + +export default { + zod: ZGeoLocation, + indexes: [[{ address: 1 }, { unique: true }]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/index.ts b/shared/models/index.ts index df6f82d07d..b23305b86c 100644 --- a/shared/models/index.ts +++ b/shared/models/index.ts @@ -2,32 +2,35 @@ export * from "./address.model" export * from "./apicalls.model" export * from "./applications.model" export * from "./appointments.model" +export * from "./computedUserAccess.model" export * from "./credentials.model" export * from "./customEmailETFA.model" +export * from "./diplomesMetiers.model" +export * from "./domainesMetiers.model" export * from "./elligibleTraining.model" export * from "./emailBlacklist.model" +export * from "./entreprise.model" export * from "./errors.model" export * from "./etablissement.model" export * from "./formation.model" export * from "./geolocations.model" export * from "./job.model" export * from "./lbaCompany.model" +export * from "./lbaCompanyLegacy.model" export * from "./lbaItem.model" export * from "./lbacError.model" -export * from "./metiers.model" export * from "./metiersdavenir.model" export * from "./optout.model" export * from "./recruiter.model" -export * from "./roleManagement.model" +export * from "./recruteurLbaUpdateEvent.model" export * from "./referentielOnisep.model" export * from "./referentielOpco.model" +export * from "./roleManagement.model" export * from "./rome.model" export * from "./session.model" export * from "./siretDiffusibleStatus.model" export * from "./unsubscribeOF.model" export * from "./unsubscribedLbaCompany.model" export * from "./user.model" -export * from "./usersRecruteur.model" export * from "./userWithAccount.model" -export * from "./computedUserAccess.model" -export * from "./recruteurLbaUpdateEvent.model" +export * from "./usersRecruteur.model" diff --git a/shared/models/internalJob.model.ts b/shared/models/internalJob.model.ts new file mode 100644 index 0000000000..07df6d7b49 --- /dev/null +++ b/shared/models/internalJob.model.ts @@ -0,0 +1,13 @@ +import { z } from "zod" + +import { IModelDescriptor } from "./common" + +const collectionName = "internalJobs" as const + +const ZInternalJobs = z.any() + +export default { + zod: ZInternalJobs, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/job.model.ts b/shared/models/job.model.ts index 9ae7ab26a4..690b82ac9b 100644 --- a/shared/models/job.model.ts +++ b/shared/models/job.model.ts @@ -5,7 +5,7 @@ import dayjs from "../helpers/dayjs" import { z } from "../helpers/zodWithOpenApi" import { zObjectId } from "./common" -import { ZReferentielRome } from "./rome.model" +import { ZReferentielRomeForJob } from "./rome.model" export enum JOB_STATUS { ACTIVE = "Active", @@ -41,7 +41,7 @@ export const ZJobFields = z job_description: z.string().nullish().describe("Description de l'offre d'alternance - minimum 30 charactères si rempli"), job_employer_description: z.string().nullish().describe("Description de l'employer proposant l'offre d'alternance - minimum 30 charactères si rempli"), rome_code: z.array(z.string()).describe("Liste des romes liés au métier"), - rome_detail: ZReferentielRome.nullish().describe("Détail du code ROME selon la nomenclature Pole emploi"), + rome_detail: ZReferentielRomeForJob.nullish().describe("Détail du code ROME selon la nomenclature Pole emploi"), job_creation_date: z.date().nullish().describe("Date de creation de l'offre"), job_expiration_date: z.date().nullish().describe("Date d'expiration de l'offre"), job_update_date: z.date().nullish().describe("Date de dernière mise à jour de l'offre"), @@ -66,7 +66,7 @@ export const ZJobFields = z custom_job_title: z.string().nullish().describe("Titre personnalisée de l'offre"), stats_detail_view: z.number().nullish().describe("Nombre de vues de la page de détail"), stats_search_view: z.number().nullish().describe("Nombre de vues sur une page de recherche"), - managed_by: zObjectId.nullish().describe("Id de l'utilisateur gérant l'offre"), + managed_by: z.string().nullish().describe("Id de l'utilisateur gérant l'offre"), }) .strict() .openapi("JobWritable") @@ -78,7 +78,7 @@ export const ZJob = ZJobFields.extend({ .openapi("Job") export const ZJobWithRomeDetail = ZJob.extend({ - rome_detail: ZReferentielRome.nullish(), + rome_detail: ZReferentielRomeForJob.nullish(), }) .strict() .openapi("JobWithRomeDetail") diff --git a/shared/models/jobs.model.ts b/shared/models/jobs.model.ts new file mode 100644 index 0000000000..1767a0637e --- /dev/null +++ b/shared/models/jobs.model.ts @@ -0,0 +1,13 @@ +import { z } from "zod" + +import { IModelDescriptor } from "./common" + +const collectionName = "jobs" as const + +const ZJobs = z.any() + +export default { + zod: ZJobs, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/lbaCompany.model.ts b/shared/models/lbaCompany.model.ts index 6ee922860a..519712bc0a 100644 --- a/shared/models/lbaCompany.model.ts +++ b/shared/models/lbaCompany.model.ts @@ -2,10 +2,13 @@ import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" import { ZPointGeometry } from "./address.model" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "bonnesboites" as const export const ZLbaCompany = z .object({ + _id: zObjectId, siret: z.string().describe("Le Siret de la société"), recruitment_potential: z.number().describe("Le score de recrutement de la société"), raison_sociale: z.string().nullable().describe("Raison sociale de l'entreprise"), @@ -30,22 +33,11 @@ export const ZLbaCompany = z created_at: z.date().describe("La date création de la demande"), last_update_at: z.date().describe("Date de dernières mise à jour"), distance: z.number().nullish().describe("Distance de la société au centre de recherche en km"), - _id: zObjectId, }) .strict() .openapi("LbaCompany") -export const ZLbaCompanyNew = ZLbaCompany.omit({ - _id: true, - created_at: true, - last_update_at: true, -}).strict() - -export const ZLbaLegacyCompany = ZLbaCompany.pick({ - siret: true, - email: true, - _id: true, -}).strict() +export type ILbaCompany = z.output export const ZLbaCompanyForContactUpdate = ZLbaCompany.pick({ siret: true, @@ -53,6 +45,16 @@ export const ZLbaCompanyForContactUpdate = ZLbaCompany.pick({ phone: true, enseigne: true, }) - -export type ILbaCompany = z.output export type ILbaCompanyForContactUpdate = z.output + +export default { + zod: ZLbaCompany, + indexes: [ + [{ siret: 1 }, {}], + [{ opco: 1 }, {}], + [{ opco_short_name: 1 }, {}], + [{ opco_url: 1 }, {}], + [{ geopoint: "2dsphere" }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/lbaCompanyLegacy.model.ts b/shared/models/lbaCompanyLegacy.model.ts new file mode 100644 index 0000000000..55299af9d2 --- /dev/null +++ b/shared/models/lbaCompanyLegacy.model.ts @@ -0,0 +1,22 @@ +import { z } from "zod" +import { zObjectId } from "zod-mongodb-schema" + +import { IModelDescriptor } from "./common" + +const collectionName = "bonnesboiteslegacies" as const + +export const ZLbaCompanyLegacy = z + .object({ + _id: zObjectId, + siret: z.string().describe("Le Siret de la société"), + email: z.string().nullable().describe("Adresse email de contact"), + }) + .strict() + +export type ILbaCompanyLegacy = z.output + +export default { + zod: ZLbaCompanyLegacy, + indexes: [[{ siret: 1 }, {}]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/lbaItem.model.ts b/shared/models/lbaItem.model.ts index c1533b9345..e5d2498292 100644 --- a/shared/models/lbaItem.model.ts +++ b/shared/models/lbaItem.model.ts @@ -4,7 +4,7 @@ import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" import { ZJobType } from "./job.model" -import { ZReferentielRome } from "./rome.model" +import { ZReferentielRomeForJob } from "./rome.model" const ZLbaItemPlace = z .object({ @@ -235,7 +235,7 @@ const ZLbaItemJob = z contractDescription: z.string().nullish(), // pe -> typeContratLibelle duration: z.string().nullish(), // pe -> dureeTravailLibelle jobStartDate: z.date().nullish(), // matcha -> offres.date_debut_apprentissage - romeDetails: ZReferentielRome.nullish(), // matcha -> offres.rome_detail -> détail du code ROME + romeDetails: ZReferentielRomeForJob.nullish(), // matcha -> offres.rome_detail -> détail du code ROME rythmeAlternance: z.string().nullish(), // matcha -> offres.rythme_alternance elligibleHandicap: z.boolean().nullish(), // matcha -> offres.is_disabled_elligible dureeContrat: z.string().nullish(), // matcha -> offres.duree_contrat @@ -480,6 +480,8 @@ export const ZLbaItemLbaJob = z .openapi("LbaJob") export type ILbaItemLbaJob = z.output +export const ZLbaItemLbaJobReturnedByAPI = z.object({ matchas: z.array(ZLbaItemLbaJob) }) +export type ILbaItemLbaJobReturnedByAPI = z.output export const ZLbaItemLbaCompany = z .object({ @@ -500,6 +502,8 @@ export const ZLbaItemLbaCompany = z .openapi("LbaCompany") export type ILbaItemLbaCompany = z.output +export const ZLbaItemLbaCompanyReturnedByAPI = z.object({ lbaCompanies: z.array(ZLbaItemLbaCompany) }) +export type ILbaItemLbaCompanyReturnedByAPI = z.output export const ZLbaItemFtJob = z .object({ @@ -520,6 +524,8 @@ export const ZLbaItemFtJob = z .openapi("PeJob") export type ILbaItemFtJob = z.output +export const ZLbaItemFtJobReturnedByAPI = z.object({ peJobs: z.array(ZLbaItemFtJob) }) +export type ILbaItemFtJobReturnedByAPI = z.output export const ZLbaItemFormationResult = z .object({ @@ -530,3 +536,4 @@ export const ZLbaItemFormationResult = z description: "Un tableau contenant la liste des formations correspondants aux critères transmis en paramètre de la requête. Le tableau peut être vide si aucune formation ne correspond.", }) +export type ILbaItemFormationResult = z.output diff --git a/shared/models/models.ts b/shared/models/models.ts new file mode 100644 index 0000000000..1216c76b8f --- /dev/null +++ b/shared/models/models.ts @@ -0,0 +1,78 @@ +import { z } from "zod" + +import apicallsModel from "./apicalls.model" +import applicationsModel from "./applications.model" +import appointmentsModel from "./appointments.model" +import cfaModel from "./cfa.model" +import { IModelDescriptor } from "./common" +import credentialsModel from "./credentials.model" +import customEmailETFAModel from "./customEmailETFA.model" +import diplomesMetiersModel from "./diplomesMetiers.model" +import domainesMetiersModel from "./domainesMetiers.model" +import elligibleTrainingModel from "./elligibleTraining.model" +import elligibleTrainingHistoryModel from "./elligibleTrainingHistory.model" +import emailBlacklistModel from "./emailBlacklist.model" +import entrepriseModel from "./entreprise.model" +import etablissementModel from "./etablissement.model" +import formationModel from "./formation.model" +import geolocationsModel from "./geolocations.model" +import internalJobModel from "./internalJob.model" +import jobsModel from "./jobs.model" +import lbaCompanyModel from "./lbaCompany.model" +import lbaCompanyLegacyModel from "./lbaCompanyLegacy.model" +import opcoModel from "./opco.model" +import optoutModel from "./optout.model" +import recruiterModel from "./recruiter.model" +import recruteurLbaUpdateEventModel from "./recruteurLbaUpdateEvent.model" +import referentielOnisepModel from "./referentielOnisep.model" +import referentielOpcoModel from "./referentielOpco.model" +import roleManagementModel from "./roleManagement.model" +import romeModel from "./rome.model" +import sessionModel from "./session.model" +import siretDiffusibleStatusModel from "./siretDiffusibleStatus.model" +import unsubscribedLbaCompanyModel from "./unsubscribedLbaCompany.model" +import unsubscribeOFModel from "./unsubscribeOF.model" +import userModel from "./user.model" +import userWithAccountModel from "./userWithAccount.model" + +const modelDescriptorMap = { + [appointmentsModel.collectionName]: appointmentsModel, + [apicallsModel.collectionName]: apicallsModel, + [applicationsModel.collectionName]: applicationsModel, + [cfaModel.collectionName]: cfaModel, + [credentialsModel.collectionName]: credentialsModel, + [customEmailETFAModel.collectionName]: customEmailETFAModel, + [diplomesMetiersModel.collectionName]: diplomesMetiersModel, + [domainesMetiersModel.collectionName]: domainesMetiersModel, + [elligibleTrainingModel.collectionName]: elligibleTrainingModel, + [elligibleTrainingHistoryModel.collectionName]: elligibleTrainingHistoryModel, + [emailBlacklistModel.collectionName]: emailBlacklistModel, + [entrepriseModel.collectionName]: entrepriseModel, + [etablissementModel.collectionName]: etablissementModel, + [formationModel.collectionName]: formationModel, + [geolocationsModel.collectionName]: geolocationsModel, + [internalJobModel.collectionName]: internalJobModel, + [jobsModel.collectionName]: jobsModel, + [lbaCompanyModel.collectionName]: lbaCompanyModel, + [lbaCompanyLegacyModel.collectionName]: lbaCompanyLegacyModel, + [opcoModel.collectionName]: opcoModel, + [optoutModel.collectionName]: optoutModel, + [recruiterModel.collectionName]: recruiterModel, + [recruteurLbaUpdateEventModel.collectionName]: recruteurLbaUpdateEventModel, + [referentielOnisepModel.collectionName]: referentielOnisepModel, + [referentielOpcoModel.collectionName]: referentielOpcoModel, + [romeModel.collectionName]: romeModel, + [roleManagementModel.collectionName]: roleManagementModel, + [sessionModel.collectionName]: sessionModel, + [siretDiffusibleStatusModel.collectionName]: siretDiffusibleStatusModel, + [unsubscribedLbaCompanyModel.collectionName]: unsubscribedLbaCompanyModel, + [unsubscribeOFModel.collectionName]: unsubscribeOFModel, + [userModel.collectionName]: userModel, + [userWithAccountModel.collectionName]: userWithAccountModel, +} as const satisfies Record + +export const modelDescriptors = Object.values(modelDescriptorMap) as (typeof modelDescriptorMap)[keyof typeof modelDescriptorMap][] satisfies IModelDescriptor[] + +export type CollectionName = keyof typeof modelDescriptorMap + +export type IDocument = z.output<(typeof modelDescriptorMap)[Name]["zod"]> diff --git a/shared/models/opco.model.ts b/shared/models/opco.model.ts new file mode 100644 index 0000000000..4ab01a8caa --- /dev/null +++ b/shared/models/opco.model.ts @@ -0,0 +1,30 @@ +import { z } from "../helpers/zodWithOpenApi" + +import { zObjectId, IModelDescriptor } from "./common" + +const collectionName = "opcos" as const + +export const ZOpco = z + .object({ + _id: zObjectId, + siren: z.string().describe("SIREN de l'établissement"), + opco: z.string().describe("Opco de rattachement de l'établissement"), + opco_short_name: z.string().nullish().describe("Nom court de de l'opco servant de clef dans notre table de constantes"), + idcc: z.string().nullish().describe("Identifiant convention collective"), + url: z.string().nullish().describe("Site internet de l'opco"), + }) + .strict() + +export type IOpco = z.output + +export default { + zod: ZOpco, + indexes: [ + [{ siren: 1 }, { unique: true }], + [{ opco: 1 }, {}], + [{ opco_short_name: 1 }, {}], + [{ idcc: 1 }, {}], + [{ url: 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/optout.model.ts b/shared/models/optout.model.ts index 63ecb75628..9807deeca2 100644 --- a/shared/models/optout.model.ts +++ b/shared/models/optout.model.ts @@ -1,6 +1,6 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" export const ZMail = z .object({ @@ -13,6 +13,8 @@ export const ZMail = z export type IMail = z.output +const collectionName = "optouts" as const + export const ZOptout = z .object({ _id: zObjectId, @@ -44,3 +46,9 @@ export const ZOptout = z .strict() export type IOptout = z.output + +export default { + zod: ZOptout, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/recruiter.model.ts b/shared/models/recruiter.model.ts index 44b8c570d5..5f8c666947 100644 --- a/shared/models/recruiter.model.ts +++ b/shared/models/recruiter.model.ts @@ -6,7 +6,7 @@ import { RECRUITER_STATUS } from "../constants/recruteur" import { z } from "../helpers/zodWithOpenApi" import { ZPointGeometry } from "./address.model" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" import { ZJob } from "./job.model" const allRecruiterStatus = Object.values(RECRUITER_STATUS) @@ -41,11 +41,13 @@ export const ZRecruiterWritable = z naf_label: z.string().nullish().describe("Libellé NAF de l'établissement"), establishment_size: z.string().nullish().describe("Tranche d'effectif salariale de l'établissement"), establishment_creation_date: z.date().nullish().describe("Date de creation de l'établissement"), - managed_by: zObjectId.nullish().describe("Id de l'utilisateur gestionnaire"), + managed_by: z.string().nullish().describe("Id de l'utilisateur gestionnaire"), }) .strict() .openapi("RecruiterWritable") +const collectionName = "recruiters" as const + export const ZRecruiter = ZRecruiterWritable.extend({ _id: zObjectId, distance: z.number().nullish(), @@ -79,3 +81,14 @@ export const ZAnonymizedRecruiter = ZRecruiterWritable.pick({ }).strict() export type IAnonymizedRecruiter = z.output + +export default { + zod: ZRecruiter, + indexes: [ + [{ establishment_id: 1 }, {}], + [{ establishment_siret: 1 }, {}], + [{ cfa_delegated_siret: 1 }, {}], + [{ geopoint: "2dsphere" }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/recruteurLbaUpdateEvent.model.ts b/shared/models/recruteurLbaUpdateEvent.model.ts index 217eee5574..05d29c3ed4 100644 --- a/shared/models/recruteurLbaUpdateEvent.model.ts +++ b/shared/models/recruteurLbaUpdateEvent.model.ts @@ -1,6 +1,8 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "recruteurlbaupdateevents" as const export enum ERecruteurLbaUpdateEventType { DELETE_PHONE = "DELETE_PHONE", @@ -11,11 +13,11 @@ export enum ERecruteurLbaUpdateEventType { export const ZRecruteurLbaUpdateEvent = z .object({ + _id: zObjectId, siret: z.string().describe("Le Siret de la société"), event: z.enum([Object.values(ERecruteurLbaUpdateEventType)[0], ...Object.values(ERecruteurLbaUpdateEventType).slice(1)]).describe("Le type d'événement"), value: z.string().describe("La nouvelle valeur"), created_at: z.date().describe("La date création de la demande"), - _id: zObjectId, }) .strict() @@ -26,3 +28,9 @@ export const ZRecruteurLbaUpdateEventNew = ZRecruteurLbaUpdateEvent.omit({ export type IRecruteurLbaUpdateEvent = z.output export type IRecruteurLbaUpdateEventNew = z.output + +export default { + zod: ZRecruteurLbaUpdateEvent, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/referentielOnisep.model.ts b/shared/models/referentielOnisep.model.ts index 0fe62be8b7..eace543d57 100644 --- a/shared/models/referentielOnisep.model.ts +++ b/shared/models/referentielOnisep.model.ts @@ -1,6 +1,8 @@ import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "referentieloniseps" as const export const ZReferentielOnisep = z .object({ @@ -12,3 +14,9 @@ export const ZReferentielOnisep = z .strict() export type IReferentielOnisep = z.output + +export default { + zod: ZReferentielOnisep, + indexes: [[{ id_action_ideo2: 1 }, {}]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/referentielOpco.model.ts b/shared/models/referentielOpco.model.ts index 85421021b6..d8ae2d563b 100644 --- a/shared/models/referentielOpco.model.ts +++ b/shared/models/referentielOpco.model.ts @@ -2,7 +2,9 @@ import { OPCOS } from "../constants/recruteur" import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "referentielopcos" as const export const ZReferentielOpco = z .object({ @@ -20,3 +22,12 @@ export const ZReferentielOpcoInsert = ZReferentielOpco.pick({ }) export type IReferentielOpco = z.output + +export default { + zod: ZReferentielOpco, + indexes: [ + [{ siret_code: 1 }, {}], + [{ emails: 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/roleManagement.model.ts b/shared/models/roleManagement.model.ts index 1b99e8eadc..f04c1d7f7b 100644 --- a/shared/models/roleManagement.model.ts +++ b/shared/models/roleManagement.model.ts @@ -2,7 +2,7 @@ import { Jsonify } from "type-fest" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" import { enumToZod } from "./enumToZod" import { ZValidationUtilisateur } from "./userWithAccount.model" @@ -32,6 +32,8 @@ export const ZRoleManagementEvent = z export const ZAccessEntityType = enumToZod(AccessEntityType) +const collectionName = "rolemanagements" as const + export const ZRoleManagement = z .object({ _id: zObjectId, @@ -48,3 +50,14 @@ export const ZRoleManagement = z export type IRoleManagement = z.output export type IRoleManagementJson = Jsonify> export type IRoleManagementEvent = z.output + +export default { + zod: ZRoleManagement, + indexes: [ + [{ authorized_id: 1 }, {}], + [{ authorized_type: 1 }, {}], + [{ user_id: 1 }, {}], + [{ user_id: 1, authorized_id: 1, authorized_type: 1 }, { unique: true }], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/rome.model.ts b/shared/models/rome.model.ts index 31e56d6b22..6517dba1e4 100644 --- a/shared/models/rome.model.ts +++ b/shared/models/rome.model.ts @@ -1,3 +1,5 @@ +import { IModelDescriptor, zObjectId } from "shared/models/common" + import { z } from "../helpers/zodWithOpenApi" const ZCompetenceV4 = z @@ -131,7 +133,7 @@ const ZRomeMobilite = z }) .strict() -export const ZReferentielRome = z +export const ZReferentielRomeForJob = z .object({ numero: z.string(), rome: ZRome, @@ -147,4 +149,15 @@ export const ZReferentielRome = z export type IRome = z.output export type IRomeMobilite = z.output + +export const ZReferentielRome = ZReferentielRomeForJob.extend({ + _id: zObjectId, +}) + export type IReferentielRome = z.output + +export default { + zod: ZReferentielRome, + indexes: [[{ "rome.code_rome": 1 }, {}]], + collectionName: "referentielromes" as const, +} as const satisfies IModelDescriptor diff --git a/shared/models/session.model.ts b/shared/models/session.model.ts index 1249be689e..e42b2ffcbb 100644 --- a/shared/models/session.model.ts +++ b/shared/models/session.model.ts @@ -4,16 +4,13 @@ import { z } from "../helpers/zodWithOpenApi" import { IModelDescriptor, zObjectId } from "./common" -const collectionName = "sessions" as const - -const indexes: IModelDescriptor["indexes"] = [] - export const ZSession = z .object({ _id: zObjectId, token: z.string().describe("Token de la session"), updated_at: z.date().optional().describe("Date de mise à jour en base de données"), created_at: z.date().optional().describe("Date d'ajout en base de données"), + expires_at: z.date().optional().describe("Date d'expiration en base de données"), }) .strict() @@ -22,6 +19,10 @@ export type ISessionJson = Jsonify> export default { zod: ZSession, - indexes, - collectionName, -} + indexes: [ + [{ token: 1 }, {}], + // TODO + // [{ expires_at: 1 }, { expireAfterSeconds: config.auth.session.cookie.maxAge / 100 }], + ], + collectionName: "sessions" as const, +} as const satisfies IModelDescriptor diff --git a/shared/models/siretDiffusibleStatus.model.ts b/shared/models/siretDiffusibleStatus.model.ts index 69ae8d9ab9..37037a3d46 100644 --- a/shared/models/siretDiffusibleStatus.model.ts +++ b/shared/models/siretDiffusibleStatus.model.ts @@ -1,16 +1,22 @@ import { EDiffusibleStatus } from "../constants/diffusibleStatus" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" export const ZSiretDiffusibleStatus = z .object({ _id: zObjectId, siret: z.string(), - status_diffusion: z.enum([Object.values(EDiffusibleStatus)[0], ...Object.values(EDiffusibleStatus).slice(1)]), - creation_date: z.coerce.date(), - last_update_date: z.coerce.date(), + status_diffusion: z.enum([Object.values(EDiffusibleStatus)[0], ...Object.values(EDiffusibleStatus).slice(1)]).default(EDiffusibleStatus.DIFFUSIBLE), + created_at: z.coerce.date(), + last_update_at: z.coerce.date(), }) .strict() export type ISiretDiffusibleStatus = z.output + +export default { + zod: ZSiretDiffusibleStatus, + indexes: [[{ siret: 1 }, { unique: true }]], + collectionName: "siretdiffusiblestatuses" as const, +} as const satisfies IModelDescriptor diff --git a/shared/models/unsubscribeOF.model.ts b/shared/models/unsubscribeOF.model.ts index bf7c060f26..0a785ce5c3 100644 --- a/shared/models/unsubscribeOF.model.ts +++ b/shared/models/unsubscribeOF.model.ts @@ -1,7 +1,9 @@ import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "unsubscribedofs" as const export const ZUnsubscribeOF = z .object({ @@ -13,3 +15,12 @@ export const ZUnsubscribeOF = z .strict() export type IUnsubscribedOF = z.output + +export default { + zod: ZUnsubscribeOF, + indexes: [ + [{ catalogue_id: 1 }, {}], + [{ establishment_siret: 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/unsubscribedLbaCompany.model.ts b/shared/models/unsubscribedLbaCompany.model.ts index e17a237979..52c9730f7d 100644 --- a/shared/models/unsubscribedLbaCompany.model.ts +++ b/shared/models/unsubscribedLbaCompany.model.ts @@ -1,7 +1,10 @@ import { z } from "../helpers/zodWithOpenApi" +import { IModelDescriptor } from "./common" import { ZLbaCompany } from "./lbaCompany.model" +const collectionName = "unsubscribedbonnesboites" as const + export const ZUnsubscribedLbaCompany = ZLbaCompany.pick({ _id: true, siret: true, @@ -24,3 +27,9 @@ export const ZUnsubscribedLbaCompany = ZLbaCompany.pick({ .strict() export type IUnsubscribedLbaCompany = z.output + +export default { + zod: ZUnsubscribedLbaCompany, + indexes: [], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/user.model.ts b/shared/models/user.model.ts index 35a36bea50..74fee7564b 100644 --- a/shared/models/user.model.ts +++ b/shared/models/user.model.ts @@ -1,7 +1,9 @@ import { EApplicantRole, EApplicantType } from "../constants/rdva" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" + +const collectionName = "users" as const export const ZUser = z .object({ @@ -17,3 +19,9 @@ export const ZUser = z .strict() export type IUser = z.output + +export default { + zod: ZUser, + indexes: [[{ email: 1 }, {}]], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/models/userWithAccount.model.ts b/shared/models/userWithAccount.model.ts index 883fafe86e..f2d1bc1d6f 100644 --- a/shared/models/userWithAccount.model.ts +++ b/shared/models/userWithAccount.model.ts @@ -4,7 +4,7 @@ import { ADMIN, OPCO, OPCOS, VALIDATION_UTILISATEUR } from "../constants/recrute import { extensions } from "../helpers/zodHelpers/zodPrimitives" import { z } from "../helpers/zodWithOpenApi" -import { zObjectId } from "./common" +import { IModelDescriptor, zObjectId } from "./common" import { enumToZod } from "./enumToZod" export enum UserEventType { @@ -27,6 +27,8 @@ export const ZUserStatusEvent = z export type IUserStatusEvent = z.output export type IUserStatusEventJson = Jsonify> +const collectionName = "userswithaccounts" as const + export const ZUserWithAccount = z .object({ _id: zObjectId, @@ -62,3 +64,13 @@ export const ZNewSuperUser = z.union([ }), ]) export type INewSuperUser = z.output + +export default { + zod: ZUserWithAccount, + indexes: [ + [{ email: 1 }, { unique: true }], + [{ last_action_date: 1 }, {}], + [{ "status.status": 1 }, {}], + ], + collectionName, +} as const satisfies IModelDescriptor diff --git a/shared/package.json b/shared/package.json index 7528b5b0f1..0333567c3f 100644 --- a/shared/package.json +++ b/shared/package.json @@ -17,17 +17,18 @@ "dependencies": { "@asteasolutions/zod-to-openapi": "^5.5.0", "@fastify/swagger": "^8.11.0", - "bson": "^1.1.4", + "bson": "^6.7.0", "dayjs": "^1.11.10", "lodash-es": "^4.17.21", "luhn": "^2.4.1", "type-fest": "^4.18.2", - "zod": "3.21.4" + "zod": "3.23.8", + "zod-mongodb-schema": "^1.0.2" }, "devDependencies": { "@types/boom": "^7.3.3", "eslint-plugin-zod": "^1.4.0", - "mongodb": "^3.7.4", - "typescript": "^5.2.2" + "mongodb": "^6.7.0", + "typescript": "^5.4.5" } } diff --git a/shared/routes/core.routes.ts b/shared/routes/core.routes.ts index 2ef7a81809..3759e5f449 100644 --- a/shared/routes/core.routes.ts +++ b/shared/routes/core.routes.ts @@ -4,12 +4,10 @@ import { IRoutesDef, ZResError } from "./common.routes" const zResponse = z .object({ + name: z.string(), + version: z.string(), env: z.enum(["local", "recette", "pentest", "production", "preview"]), - healthcheck: z - .object({ - mongodb: z.boolean(), - }) - .strict(), + mongo: z.boolean(), }) .strict() diff --git a/shared/routes/index.ts b/shared/routes/index.ts index 70a21e985b..407adb5620 100644 --- a/shared/routes/index.ts +++ b/shared/routes/index.ts @@ -183,8 +183,6 @@ export type IRequestFetchOptions = { headers?: Record } -export type IRequest = ConditionalExcept, never | EmptyObject> extends EmptyObject - ? EmptyObject - : ConditionalExcept, never | EmptyObject> +export type IRequest = ConditionalExcept, never> export type IApiVersion = "V1" | "V2" diff --git a/shared/routes/metiers.routes.ts b/shared/routes/metiers.routes.ts index b983f18c09..94b7fbaa23 100644 --- a/shared/routes/metiers.routes.ts +++ b/shared/routes/metiers.routes.ts @@ -1,5 +1,5 @@ import { z } from "../helpers/zodWithOpenApi" -import { ZAppellationsRomes, ZMetierEnrichiArray, ZMetiers } from "../models/metiers.model" +import { ZAppellationsRomes, ZMetierEnrichiArray, ZMetiers } from "../models/diplomesMetiers.model" import { rateLimitDescription } from "../utils/rateLimitDescription" import { IRoutesDef } from "./common.routes" diff --git a/shared/routes/metiers.routes.v2.ts b/shared/routes/metiers.routes.v2.ts index 89e74c7283..84d362ceb2 100644 --- a/shared/routes/metiers.routes.v2.ts +++ b/shared/routes/metiers.routes.v2.ts @@ -1,5 +1,5 @@ import { z } from "../helpers/zodWithOpenApi" -import { ZAppellationsRomes, ZMetierEnrichiArray, ZMetiers } from "../models/metiers.model" +import { ZAppellationsRomes, ZMetierEnrichiArray, ZMetiers } from "../models/diplomesMetiers.model" import { rateLimitDescription } from "../utils/rateLimitDescription" import { IRoutesDef } from "./common.routes" diff --git a/shared/routes/rome.routes.ts b/shared/routes/rome.routes.ts index b421014d7e..4127a0c710 100644 --- a/shared/routes/rome.routes.ts +++ b/shared/routes/rome.routes.ts @@ -1,5 +1,5 @@ import { z } from "../helpers/zodWithOpenApi" -import { ZMetiersEnrichis, ZReferentielRome } from "../models" +import { ZMetiersEnrichis, ZReferentielRomeForJob } from "../models" import { IRoutesDef } from "./common.routes" @@ -28,7 +28,7 @@ export const zRomeRoutes = { }) .strict(), response: { - "200": ZReferentielRome, + "200": ZReferentielRomeForJob, }, securityScheme: null, }, diff --git a/shared/routes/v1Jobs.routes.ts b/shared/routes/v1Jobs.routes.ts index c46d669f95..4797965e2d 100644 --- a/shared/routes/v1Jobs.routes.ts +++ b/shared/routes/v1Jobs.routes.ts @@ -3,7 +3,14 @@ import { z } from "../helpers/zodWithOpenApi" import { ZJob, ZJobFields, ZJobStartDateCreate } from "../models" import { zObjectId } from "../models/common" import { ZApiError, ZLbacError, ZLbarError } from "../models/lbacError.model" -import { ZLbaItemFtJob, ZLbaItemLbaCompany, ZLbaItemLbaJob } from "../models/lbaItem.model" +import { + ZLbaItemFtJob, + ZLbaItemFtJobReturnedByAPI, + ZLbaItemLbaCompany, + ZLbaItemLbaCompanyReturnedByAPI, + ZLbaItemLbaJob, + ZLbaItemLbaJobReturnedByAPI, +} from "../models/lbaItem.model" import { ZRecruiter } from "../models/recruiter.model" import { rateLimitDescription } from "../utils/rateLimitDescription" @@ -301,11 +308,7 @@ export const zV1JobsRoutes = { .passthrough(), headers: zRefererHeaders, response: { - "200": z - .object({ - lbaCompanies: z.array(ZLbaItemLbaCompany), - }) - .strict(), + "200": ZLbaItemLbaCompanyReturnedByAPI, "400": z.union([ZResError, ZLbacError, ZApiError]), "404": z.union([ZResError, ZLbacError, ZApiError]), "500": z.union([ZResError, ZLbacError, ZApiError]), @@ -336,11 +339,7 @@ export const zV1JobsRoutes = { .passthrough(), headers: zRefererHeaders, response: { - "200": z - .object({ - matchas: z.array(ZLbaItemLbaJob), - }) - .strict(), + "200": ZLbaItemLbaJobReturnedByAPI, //"419": le code correspondant a disparu. ticket bug ouvert "400": z.union([ZResError, ZLbacError, ZApiError]), "500": z.union([ZResError, ZLbacError, ZApiError]), @@ -367,11 +366,7 @@ export const zV1JobsRoutes = { .passthrough(), headers: zRefererHeaders, response: { - "200": z - .object({ - peJobs: z.array(ZLbaItemFtJob), - }) - .strict(), + "200": ZLbaItemFtJobReturnedByAPI, "400": z.union([ZResError, ZLbacError, ZApiError]), "404": z.union([ZResError, ZLbacError, ZApiError]), "500": z.union([ZResError, ZLbacError, ZApiError]), diff --git a/ui/context/UserContext.tsx b/ui/context/UserContext.tsx index abe244af8c..3a27961949 100644 --- a/ui/context/UserContext.tsx +++ b/ui/context/UserContext.tsx @@ -68,7 +68,7 @@ export const UserContext = ({ } } emitter.on("http:error", handler) - return () => emitter.off("http:error", handler) + return () => emitter.removeListener("http:error", handler) }, []) if (isLoading) { diff --git a/ui/package.json b/ui/package.json index 47c5258ba2..bcc6732426 100644 --- a/ui/package.json +++ b/ui/package.json @@ -51,7 +51,7 @@ "react-table": "^7.8.0", "shared": "workspace:*", "yup": "^0.32.11", - "zod": "3.21.4", + "zod": "3.23.8", "zod-formik-adapter": "^1.3.0" }, "devDependencies": { @@ -63,6 +63,6 @@ "eslint-config-next": "latest", "nock": "^13.3.3", "type-fest": "^4.18.2", - "typescript": "^5.2.2" + "typescript": "^5.4.5" } } diff --git a/ui/services/fetchFtJobDetails.ts b/ui/services/fetchFtJobDetails.ts index 83b665c077..f02ce362ad 100644 --- a/ui/services/fetchFtJobDetails.ts +++ b/ui/services/fetchFtJobDetails.ts @@ -1,15 +1,12 @@ -import { ILbaItemFtJob, zRoutes } from "@/../shared" -import { z } from "zod" +import { ILbaItemFtJob, ILbaItemFtJobReturnedByAPI } from "@/../shared" import { apiGet } from "@/utils/api.utils" -const zodSchema = zRoutes.get["/v1/jobs/job/:id"].response["200"] - const fetchFtJobDetails = async (job: { id: string }): Promise => { - const response = await apiGet("/v1/jobs/job/:id", { params: { id: job.id }, querystring: {} }) + // KBA 2024-05-31 API should return a single object and not an array as we are only fetching a single object + const response: ILbaItemFtJobReturnedByAPI = await apiGet("/v1/jobs/job/:id", { params: { id: job.id }, querystring: {} }) - const typedResponse = response as z.output - const [firstFtJob] = typedResponse?.peJobs ?? [] + const [firstFtJob] = response?.peJobs ?? [] if (firstFtJob) { firstFtJob.detailsLoaded = true return firstFtJob diff --git a/ui/services/fetchLbaCompanyDetails.ts b/ui/services/fetchLbaCompanyDetails.ts index d69398910b..6a5462ff02 100644 --- a/ui/services/fetchLbaCompanyDetails.ts +++ b/ui/services/fetchLbaCompanyDetails.ts @@ -1,15 +1,12 @@ -import { ILbaItemLbaCompany, zRoutes } from "@/../shared" -import { z } from "zod" +import { ILbaItemLbaCompany, ILbaItemLbaCompanyReturnedByAPI } from "@/../shared" import { apiGet } from "@/utils/api.utils" -const zodSchema = zRoutes.get["/v1/jobs/company/:siret"].response["200"] - const fetchLbaCompanyDetails = async (company): Promise => { - const response = await apiGet("/v1/jobs/company/:siret", { params: { siret: company.id }, querystring: {} }) + // KBA 2024-05-31 API should return a single object and not an array as we are only fetching a single object + const response: ILbaItemLbaCompanyReturnedByAPI = await apiGet("/v1/jobs/company/:siret", { params: { siret: company.id }, querystring: {} }) - const typedResponse = response as z.output - const [firstLbaCompany] = typedResponse?.lbaCompanies ?? [] + const [firstLbaCompany] = response?.lbaCompanies ?? [] if (firstLbaCompany) { firstLbaCompany.detailsLoaded = true return firstLbaCompany diff --git a/ui/services/fetchLbaJobDetails.ts b/ui/services/fetchLbaJobDetails.ts index f1e673a216..5ae3f7f7d7 100644 --- a/ui/services/fetchLbaJobDetails.ts +++ b/ui/services/fetchLbaJobDetails.ts @@ -1,14 +1,12 @@ -import { ILbaItemLbaJob, zRoutes } from "shared" -import { z } from "zod" +import { ILbaItemLbaJob, ILbaItemLbaJobReturnedByAPI } from "shared" import { apiGet } from "@/utils/api.utils" -const zodSchema = zRoutes.get["/v1/jobs/matcha/:id"].response["200"] - const fetchLbaJobDetails = async (job): Promise => { - const response = await apiGet("/v1/jobs/matcha/:id", { params: { id: job.id }, querystring: {} }) - const typedResponse = response as z.output - const [firstMatcha] = typedResponse?.matchas ?? [] + // KBA 2024-05-31 API should return a single object and not an array as we are only fetching a single job + const response: ILbaItemLbaJobReturnedByAPI = await apiGet("/v1/jobs/matcha/:id", { params: { id: job.id }, querystring: {} }) + + const [firstMatcha] = response.matchas ?? [] if (firstMatcha) { firstMatcha.detailsLoaded = true return firstMatcha diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 712e48b3af..c87547a591 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -11,13 +11,11 @@ export default defineWorkspace([ include: ["./tests/**/*.test.ts", "**/*.test.ts"], setupFiles: ["./tests/utils/setup.ts"], globalSetup: ["./server/tests/utils/globalSetup.ts"], - // Isolate doesn't work with Mongoose - isolate: false, - // poolOptions: { - // threads: { - // singleThread: true, - // }, - // }, + clearMocks: true, + sequence: { + // Important for useMongo to be sequential + hooks: "stack", + }, }, }, { diff --git a/yarn.lock b/yarn.lock index 5c1a074945..d27bc58cfe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,10 +5,14 @@ __metadata: version: 6 cacheKey: 8 -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd +"@asamuzakjp/dom-selector@npm:^2.0.1": + version: 2.0.2 + resolution: "@asamuzakjp/dom-selector@npm:2.0.2" + dependencies: + bidi-js: ^1.0.3 + css-tree: ^2.3.1 + is-potential-custom-element-name: ^1.0.1 + checksum: a454537fcba4f241d3c1303f6068944462fc0ba9cd2c5e3ad639c0acb58ffb7809e5d4cbdac805c8c2525b2450d53a992ff98f07a323c5246044e8e3de3561fe languageName: node linkType: hard @@ -23,67 +27,156 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.21.4": - version: 7.23.5 - resolution: "@babel/code-frame@npm:7.23.5" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" dependencies: - "@babel/highlight": ^7.23.4 - chalk: ^2.4.2 - checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + "@babel/highlight": ^7.24.7 + picocolors: ^1.0.0 + checksum: 830e62cd38775fdf84d612544251ce773d544a8e63df667728cc9e0126eeef14c6ebda79be0f0bc307e8318316b7f58c27ce86702e0a1f5c321d842eb38ffda4 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/generator@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + jsesc: ^2.5.1 + checksum: 0ff31a73b15429f1287e4d57b439bba4a266f8c673bb445fe313b82f6d110f586776997eb723a777cd7adad9d340edd162aea4973a90112c5d0cfcaf6686844b + languageName: node + linkType: hard + +"@babel/helper-environment-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-environment-visitor@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 079d86e65701b29ebc10baf6ed548d17c19b808a07aa6885cc141b690a78581b180ee92b580d755361dc3b16adf975b2d2058b8ce6c86675fcaf43cf22f2f7c6 + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-function-name@npm:7.24.7" + dependencies: + "@babel/template": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 142ee08922074dfdc0ff358e09ef9f07adf3671ab6eef4fca74dcf7a551f1a43717e7efa358c9e28d7eea84c28d7f177b7a58c70452fc312ae3b1893c5dab2a4 + languageName: node + linkType: hard + +"@babel/helper-hoist-variables@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-hoist-variables@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 6cfdcf2289cd12185dcdbdf2435fa8d3447b797ac75851166de9fc8503e2fd0021db6baf8dfbecad3753e582c08e6a3f805c8d00cbed756060a877d705bd8d8d languageName: node linkType: hard "@babel/helper-module-imports@npm:^7.16.7": - version: 7.22.15 - resolution: "@babel/helper-module-imports@npm:7.22.15" + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 8ac15d96d262b8940bc469052a048e06430bba1296369be695fabdf6799f201dd0b00151762b56012a218464e706bc033f27c07f6cec20c6f8f5fd6543c67054 + languageName: node + linkType: hard + +"@babel/helper-split-export-declaration@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-split-export-declaration@npm:7.24.7" dependencies: - "@babel/types": ^7.22.15 - checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + "@babel/types": ^7.24.7 + checksum: e3ddc91273e5da67c6953f4aa34154d005a00791dc7afa6f41894e768748540f6ebcac5d16e72541aea0c89bee4b89b4da6a3d65972a0ea8bfd2352eda5b7e22 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/helper-string-parser@npm:7.23.4" - checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 +"@babel/helper-string-parser@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-string-parser@npm:7.24.7" + checksum: 09568193044a578743dd44bf7397940c27ea693f9812d24acb700890636b376847a611cdd0393a928544e79d7ad5b8b916bd8e6e772bc8a10c48a647a96e7b1a languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 6799ab117cefc0ecd35cd0b40ead320c621a298ecac88686a14cffceaac89d80cdb3c178f969861bf5fa5e4f766648f9161ea0752ecfe080d8e89e3147270257 languageName: node linkType: hard -"@babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" dependencies: - "@babel/helper-validator-identifier": ^7.22.20 + "@babel/helper-validator-identifier": ^7.24.7 chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + picocolors: ^1.0.0 + checksum: 5cd3a89f143671c4ac129960024ba678b669e6fc673ce078030f5175002d1d3d52bc10b22c5b916a6faf644b5028e9a4bd2bb264d053d9b05b6a98690f1d46f1 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/parser@npm:7.24.7" + bin: + parser: ./bin/babel-parser.js + checksum: fc9d2c4c8712f89672edc55c0dc5cf640dcec715b56480f111f85c2bc1d507e251596e4110d65796690a96ac37a4b60432af90b3e97bb47e69d4ef83872dbbd6 languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.9.1": - version: 7.23.7 - resolution: "@babel/runtime@npm:7.23.7" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.9.1": + version: 7.24.7 + resolution: "@babel/runtime@npm:7.24.7" dependencies: regenerator-runtime: ^0.14.0 - checksum: eba85bd24d250abb5ae19b16cffc15a54d3894d8228ace40fa4c0e2f1938f28b38ad3e3430ebff9a1ef511eeb8c527e36044ac19076d6deafa52cef35d8624b9 + checksum: d17f29eed6f848ac15cdf4202a910b741facfb0419a9d79e5c7fa37df6362fc3227f1cc2e248cc6db5e53ddffb4caa6686c488e6e80ce3d29c36a4e74c8734ea + languageName: node + linkType: hard + +"@babel/template@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/template@npm:7.24.7" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/parser": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: ea90792fae708ddf1632e54c25fe1a86643d8c0132311f81265d2bdbdd42f9f4fac65457056c1b6ca87f7aa0d6a795b549566774bba064bdcea2034ab3960ee9 + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/traverse@npm:7.24.7" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.24.7 + "@babel/helper-environment-visitor": ^7.24.7 + "@babel/helper-function-name": ^7.24.7 + "@babel/helper-hoist-variables": ^7.24.7 + "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/parser": ^7.24.7 + "@babel/types": ^7.24.7 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: 7cd366afe9e7ee77e493779fdf24f67bf5595247289364f4689e29688572505eaeb886d7a8f20ebb9c29fc2de7d0895e4ff9e203e78e39ac67239724d45aa83b languageName: node linkType: hard -"@babel/types@npm:^7.22.15": - version: 7.23.6 - resolution: "@babel/types@npm:7.23.6" +"@babel/types@npm:^7.24.7, @babel/types@npm:^7.8.3": + version: 7.24.7 + resolution: "@babel/types@npm:7.24.7" dependencies: - "@babel/helper-string-parser": ^7.23.4 - "@babel/helper-validator-identifier": ^7.22.20 + "@babel/helper-string-parser": ^7.24.7 + "@babel/helper-validator-identifier": ^7.24.7 to-fast-properties: ^2.0.0 - checksum: 68187dbec0d637f79bc96263ac95ec8b06d424396678e7e225492be866414ce28ebc918a75354d4c28659be6efe30020b4f0f6df81cc418a2d30645b690a8de0 + checksum: 3e4437fced97e02982972ce5bebd318c47d42c9be2152c0fd28c6f786cc74086cc0a8fb83b602b846e41df37f22c36254338eada1a47ef9d8a1ec92332ca3ea8 languageName: node linkType: hard @@ -1617,12 +1710,12 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.2.1": - version: 1.2.1 - resolution: "@emotion/is-prop-valid@npm:1.2.1" +"@emotion/is-prop-valid@npm:^1.2.2": + version: 1.2.2 + resolution: "@emotion/is-prop-valid@npm:1.2.2" dependencies: "@emotion/memoize": ^0.8.1 - checksum: 8f42dc573a3fad79b021479becb639b8fe3b60bdd1081a775d32388bca418ee53074c7602a4c845c5f75fa6831eb1cbdc4d208cc0299f57014ed3a02abcad16a + checksum: 61f6b128ea62b9f76b47955057d5d86fcbe2a6989d2cd1e583daac592901a950475a37d049b9f7a7c6aa8758a33b408735db759fdedfd1f629df0f85ab60ea25 languageName: node linkType: hard @@ -1641,8 +1734,8 @@ __metadata: linkType: hard "@emotion/react@npm:^11.11.1": - version: 11.11.3 - resolution: "@emotion/react@npm:11.11.3" + version: 11.11.4 + resolution: "@emotion/react@npm:11.11.4" dependencies: "@babel/runtime": ^7.18.3 "@emotion/babel-plugin": ^11.11.0 @@ -1657,20 +1750,20 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 2e4b223591569f0a41686d5bd72dc8778629b7be33267e4a09582979e6faee4d7218de84e76294ed827058d4384d75557b5d71724756539c1f235e9a69e62b2e + checksum: 6abaa7a05c5e1db31bffca7ac79169f5456990022cbb3794e6903221536609a60420f2b4888dd3f84e9634a304e394130cb88dc32c243a1dedc263e50da329f8 languageName: node linkType: hard -"@emotion/serialize@npm:^1.1.2, @emotion/serialize@npm:^1.1.3": - version: 1.1.3 - resolution: "@emotion/serialize@npm:1.1.3" +"@emotion/serialize@npm:^1.1.2, @emotion/serialize@npm:^1.1.3, @emotion/serialize@npm:^1.1.4": + version: 1.1.4 + resolution: "@emotion/serialize@npm:1.1.4" dependencies: "@emotion/hash": ^0.9.1 "@emotion/memoize": ^0.8.1 "@emotion/unitless": ^0.8.1 "@emotion/utils": ^1.2.1 csstype: ^3.0.2 - checksum: 5a756ce7e2692322683978d8ed2e84eadd60bd6f629618a82c5018c84d98684b117e57fad0174f68ec2ec0ac089bb2e0bcc8ea8c2798eb904b6d3236aa046063 + checksum: 71b99f816a9c1d61a87c62cf4928da3894bb62213f3aff38b1ea9790b3368f084af98a3e5453b5055c2f36a7d70318d2fa9955b7b5676c2065b868062375df39 languageName: node linkType: hard @@ -1682,13 +1775,13 @@ __metadata: linkType: hard "@emotion/styled@npm:^11.11.0": - version: 11.11.0 - resolution: "@emotion/styled@npm:11.11.0" + version: 11.11.5 + resolution: "@emotion/styled@npm:11.11.5" dependencies: "@babel/runtime": ^7.18.3 "@emotion/babel-plugin": ^11.11.0 - "@emotion/is-prop-valid": ^1.2.1 - "@emotion/serialize": ^1.1.2 + "@emotion/is-prop-valid": ^1.2.2 + "@emotion/serialize": ^1.1.4 "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 "@emotion/utils": ^1.2.1 peerDependencies: @@ -1697,7 +1790,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 904f641aad3892c65d7d6c0808b036dae1e6d6dad4861c1c7dc0baa59977047c6cad220691206eba7b4059f1a1c6e6c1ef4ebb8c829089e280fa0f2164a01e6b + checksum: ad5fc42d00e8aa9597f6d9665986036d5ebe0e8f8155af6d95831c5e8fb2319fb837724e6c5cd59e5346f14c3263711b7ce7271d34688e974d1f32ffeecb37ba languageName: node linkType: hard @@ -1731,9 +1824,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/aix-ppc64@npm:0.20.2" +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard @@ -1745,9 +1838,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-arm64@npm:0.20.2" +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -1759,9 +1852,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-arm@npm:0.20.2" +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -1773,9 +1866,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-x64@npm:0.20.2" +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -1787,9 +1880,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/darwin-arm64@npm:0.20.2" +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -1801,9 +1894,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/darwin-x64@npm:0.20.2" +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -1815,9 +1908,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/freebsd-arm64@npm:0.20.2" +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -1829,9 +1922,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/freebsd-x64@npm:0.20.2" +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -1843,9 +1936,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-arm64@npm:0.20.2" +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -1857,9 +1950,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-arm@npm:0.20.2" +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -1871,9 +1964,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-ia32@npm:0.20.2" +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -1885,9 +1978,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-loong64@npm:0.20.2" +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -1899,9 +1992,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-mips64el@npm:0.20.2" +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -1913,9 +2006,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-ppc64@npm:0.20.2" +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -1927,9 +2020,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-riscv64@npm:0.20.2" +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -1941,9 +2034,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-s390x@npm:0.20.2" +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -1955,9 +2048,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-x64@npm:0.20.2" +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -1969,9 +2062,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/netbsd-x64@npm:0.20.2" +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -1983,9 +2076,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/openbsd-x64@npm:0.20.2" +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -1997,9 +2090,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/sunos-x64@npm:0.20.2" +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -2011,9 +2104,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-arm64@npm:0.20.2" +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -2025,9 +2118,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-ia32@npm:0.20.2" +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -2039,22 +2132,22 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-x64@npm:0.20.2" +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@eslint-community/eslint-plugin-eslint-comments@npm:^4.1.0": - version: 4.1.0 - resolution: "@eslint-community/eslint-plugin-eslint-comments@npm:4.1.0" + version: 4.3.0 + resolution: "@eslint-community/eslint-plugin-eslint-comments@npm:4.3.0" dependencies: escape-string-regexp: ^4.0.0 ignore: ^5.2.4 peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: e4274499269e2981146a038d7e1a83cc442a54f5d8a7757acacbfeb9ff1be967a75b6594d59a2b01ea1a081b39ed03104c1f1d894ec53795019f1eaf39f8dc86 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: f79cd9b184435e5718b0323e28e29a2f9f7cf304d3380337c97bc8cf5ce50505cc13f6906985224da09439e1758f1c2557760fd4966bc3fd1c94e402400e7a7a languageName: node linkType: hard @@ -2069,10 +2162,10 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.0, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.0, @eslint-community/regexpp@npm:^4.6.1": + version: 4.10.1 + resolution: "@eslint-community/regexpp@npm:4.10.1" + checksum: 1e04bc366fb8152c9266258cd25e3fded102f1d212a9476928e3cb98c48be645df6d676728d1c596053992fb9134879fe0de23c9460035b342cceb22d3af1776 languageName: node linkType: hard @@ -2093,10 +2186,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.56.0": - version: 8.56.0 - resolution: "@eslint/js@npm:8.56.0" - checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb languageName: node linkType: hard @@ -2119,12 +2212,12 @@ __metadata: linkType: hard "@fastify/cookie@npm:^9.1.0": - version: 9.2.0 - resolution: "@fastify/cookie@npm:9.2.0" + version: 9.3.1 + resolution: "@fastify/cookie@npm:9.3.1" dependencies: cookie-signature: ^1.1.0 fastify-plugin: ^4.0.0 - checksum: 81e7c40c8c2a92c3c45978953faca2c6b8855d9413697aebeaabf37285ea06e696f3a07f789a671edb9837c217750f8977a168e4feed5295031e32ef5b8a5621 + checksum: d2d28679af9c00bbaab68a96aae63cf3f9f1cf8932213f6d70a8613507824979f0a5a8205e741fd936e49ad613fb6abf2a4dea0cfc57952efebef6b0ee241f03 languageName: node linkType: hard @@ -2138,14 +2231,7 @@ __metadata: languageName: node linkType: hard -"@fastify/deepmerge@npm:^1.0.0": - version: 1.3.0 - resolution: "@fastify/deepmerge@npm:1.3.0" - checksum: 33ec927905dca320d7ae9535a1521909f7c82339706345324ab6287ad100589a799b8257c15b0e582c7bb74e2aa4883d82ba0228d7b116aa8789ada4f78d6974 - languageName: node - linkType: hard - -"@fastify/error@npm:^3.4.0": +"@fastify/error@npm:^3.3.0, @fastify/error@npm:^3.4.0": version: 3.4.1 resolution: "@fastify/error@npm:3.4.1" checksum: 2c2e98c33327884c0927a73e8c3b8f162acbf1e4d058bacb68bca0c3607f36d6fde8c376fde45b2097e724d450266f8bb29134305fa24aabd200f83f087c7321 @@ -2161,6 +2247,15 @@ __metadata: languageName: node linkType: hard +"@fastify/merge-json-schemas@npm:^0.1.0": + version: 0.1.1 + resolution: "@fastify/merge-json-schemas@npm:0.1.1" + dependencies: + fast-deep-equal: ^3.1.3 + checksum: d5b976f82e6d5d30a603345a29edb176a14866b98dd4d30aabe6e58a91dfc34fb1c2dd97289bdd7f4d1e11675c9dbb9382138968742d2ac8c6fdcc5f7bd08b97 + languageName: node + linkType: hard + "@fastify/rate-limit@npm:^9.0.1": version: 9.1.0 resolution: "@fastify/rate-limit@npm:9.1.0" @@ -2213,15 +2308,15 @@ __metadata: linkType: hard "@fastify/swagger@npm:^8.10.1, @fastify/swagger@npm:^8.11.0": - version: 8.13.0 - resolution: "@fastify/swagger@npm:8.13.0" + version: 8.14.0 + resolution: "@fastify/swagger@npm:8.14.0" dependencies: fastify-plugin: ^4.0.0 json-schema-resolver: ^2.0.0 openapi-types: ^12.0.0 rfdc: ^1.3.0 yaml: ^2.2.2 - checksum: b66ce66835b657055f961e11ea900949c048bd6a0f0b4ad93b82ff45306cb008be249be56af4718f4f2e5913f0e2be6a4a5c3623347c6da30558a8bc9b0b4656 + checksum: 1ad3c84535abecd93ef5f92363775966ae169f95a2d9398c387e2b55b9db2296b4779be3919ea5859bfda65753221e6b3aecff4fefa14c898787000576b9d941 languageName: node linkType: hard @@ -2232,14 +2327,14 @@ __metadata: languageName: node linkType: hard -"@hapi/hoek@npm:^9.0.0": +"@hapi/hoek@npm:^9.0.0, @hapi/hoek@npm:^9.3.0": version: 9.3.0 resolution: "@hapi/hoek@npm:9.3.0" checksum: 4771c7a776242c3c022b168046af4e324d116a9d2e1d60631ee64f474c6e38d1bb07092d898bf95c7bc5d334c5582798a1456321b2e53ca817d4e7c88bc25b43 languageName: node linkType: hard -"@hapi/topo@npm:^5.0.0": +"@hapi/topo@npm:^5.1.0": version: 5.1.0 resolution: "@hapi/topo@npm:5.1.0" dependencies: @@ -2248,14 +2343,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": - version: 0.11.13 - resolution: "@humanwhocodes/config-array@npm:0.11.13" +"@humanwhocodes/config-array@npm:^0.11.14": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: - "@humanwhocodes/object-schema": ^2.0.1 - debug: ^4.1.1 + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 minimatch: ^3.0.5 - checksum: f8ea57b0d7ed7f2d64cd3944654976829d9da91c04d9c860e18804729a33f7681f78166ef4c761850b8c324d362f7d53f14c5c44907a6b38b32c703ff85e4805 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 languageName: node linkType: hard @@ -2266,10 +2361,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 24929487b1ed48795d2f08346a0116cc5ee4634848bce64161fb947109352c562310fd159fc64dda0e8b853307f5794605191a9547f7341158559ca3c8262a45 +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 languageName: node linkType: hard @@ -2316,28 +2411,28 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" +"@jridgewell/gen-mapping@npm:^0.3.2, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" dependencies: - "@jridgewell/set-array": ^1.0.1 + "@jridgewell/set-array": ^1.2.1 "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab + "@jridgewell/trace-mapping": ^0.3.24 + checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 languageName: node linkType: hard "@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 languageName: node linkType: hard @@ -2358,13 +2453,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.20 - resolution: "@jridgewell/trace-mapping@npm:0.3.20" +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: "@jridgewell/resolve-uri": ^3.1.0 "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: cd1a7353135f385909468ff0cf20bdd37e59f2ee49a13a966dedf921943e222082c583ade2b579ff6cd0d8faafcb5461f253e1bf2a9f48fec439211fdbe788f5 + checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 languageName: node linkType: hard @@ -2448,15 +2543,24 @@ __metadata: languageName: node linkType: hard +"@mongodb-js/saslprep@npm:^1.1.5": + version: 1.1.7 + resolution: "@mongodb-js/saslprep@npm:1.1.7" + dependencies: + sparse-bitfield: ^3.0.3 + checksum: 27e0ae6d4741b89183f2cf4fe2167756f26c9b9a73804d8e72f33e016cd54abf0a987254870da37b62dbf741be075743a35a0b6cd507ad496f258983c7c3a240 + languageName: node + linkType: hard + "@motionone/animation@npm:^10.12.0": - version: 10.16.3 - resolution: "@motionone/animation@npm:10.16.3" + version: 10.18.0 + resolution: "@motionone/animation@npm:10.18.0" dependencies: - "@motionone/easing": ^10.16.3 - "@motionone/types": ^10.16.3 - "@motionone/utils": ^10.16.3 + "@motionone/easing": ^10.18.0 + "@motionone/types": ^10.17.1 + "@motionone/utils": ^10.18.0 tslib: ^2.3.1 - checksum: 797cacea335e6f892af27579eff51450dcf18c5bbc5c0ca44a000929b21857f4afb974ffb411c4935bfbd01ef2ddb3ef542ba3313ae66e1e5392b5d314df6ad3 + checksum: 841cb9f4843a89e5e4560b9f960f52cbe78afc86f87c769f71e9edb3aadd53fb87982b7e11914428f228b29fd580756be531369c2ffac06432550afa4e87d1c3 languageName: node linkType: hard @@ -2474,49 +2578,49 @@ __metadata: languageName: node linkType: hard -"@motionone/easing@npm:^10.16.3": - version: 10.16.3 - resolution: "@motionone/easing@npm:10.16.3" +"@motionone/easing@npm:^10.18.0": + version: 10.18.0 + resolution: "@motionone/easing@npm:10.18.0" dependencies: - "@motionone/utils": ^10.16.3 + "@motionone/utils": ^10.18.0 tslib: ^2.3.1 - checksum: 03e2460cdd35ee4967a86ce28ffbaaaca589263f659f652801cf6bd667baba9b3d5ce6d134df6b64413b60b34dd21d7c38b0cd8a4c3e1ed789789cdb971905b2 + checksum: 6bd37f7a9d5a88f868cc0ad6e47d2ba8d9fefd7da84fccfea7ed77ec08c2e6d1e42df88dda462665102a5cf03f748231a1a077de7054b5a8ccb0fbf36f61b1e7 languageName: node linkType: hard "@motionone/generators@npm:^10.12.0": - version: 10.16.4 - resolution: "@motionone/generators@npm:10.16.4" + version: 10.18.0 + resolution: "@motionone/generators@npm:10.18.0" dependencies: - "@motionone/types": ^10.16.3 - "@motionone/utils": ^10.16.3 + "@motionone/types": ^10.17.1 + "@motionone/utils": ^10.18.0 tslib: ^2.3.1 - checksum: 185091c5cfbe67c38e84bf3920d1b5862e5d7eb624136494a7e4779b2f9d06855ebe3e633d95dcc5a1735d92d59d1ae28a0724c2f9d8bddd60fc9bc3603fab48 + checksum: 51a0e075681697b11d0771998cac8c76a745f00141502f81adb953896992b7f49478965e4afe696bc83361afaae8d2f1057d71c25b21035fe67258ff73764f1c languageName: node linkType: hard -"@motionone/types@npm:^10.12.0, @motionone/types@npm:^10.16.3": - version: 10.16.3 - resolution: "@motionone/types@npm:10.16.3" - checksum: ff38982f5aff2c0abbc3051c843d186d6f954c971e97dd6fced97a4ef50ee04f6e49607541ebb80e14dd143cf63553c388392110e270d04eca23f6b529f7f321 +"@motionone/types@npm:^10.12.0, @motionone/types@npm:^10.17.1": + version: 10.17.1 + resolution: "@motionone/types@npm:10.17.1" + checksum: 3fa74db64e371e61a7f7669d7d541d11c9a8dd871032d59c69041e3b2e07a67ad2ed8767cb9273bac90eed4e1f76efc1f14c8673c2e9a288f6070ee0fef64a25 languageName: node linkType: hard -"@motionone/utils@npm:^10.12.0, @motionone/utils@npm:^10.16.3": - version: 10.16.3 - resolution: "@motionone/utils@npm:10.16.3" +"@motionone/utils@npm:^10.12.0, @motionone/utils@npm:^10.18.0": + version: 10.18.0 + resolution: "@motionone/utils@npm:10.18.0" dependencies: - "@motionone/types": ^10.16.3 + "@motionone/types": ^10.17.1 hey-listen: ^1.0.8 tslib: ^2.3.1 - checksum: d06025911c54c2217c98026cd38d4d681268a2b9b2830ac7342820881ba6be09721dd03626f52547749ead0543d5e2f2a69c9270ffdeaabc0949f7afb3233817 + checksum: a27f9afde693a0cbbbcb33962b12bbe40dd2cfa514b0732f3c7953c5ef4beed738e1e8172a2de89e3b9f74a253ef0a70d7f3efb730be97b77d7176a3ffacb67a languageName: node linkType: hard -"@next/env@npm:14.0.4": - version: 14.0.4 - resolution: "@next/env@npm:14.0.4" - checksum: e8dac033d92c10e55d3b1802f8fd9be00383ed9d479add9fee0823a9a0bf2ab0f4421d5baea52921871c82daf5cd292421db8a1ed5d173e3cb088c3b3a984c0d +"@next/env@npm:14.2.4": + version: 14.2.4 + resolution: "@next/env@npm:14.2.4" + checksum: ff47297f959c4f4a45393fc84eb2cdef0e92fb07903e1240e061ff71c2319d90d3faf23aa6f8e5747451a26527ab20b483a200845ac9c72629647d67407b15c2 languageName: node linkType: hard @@ -2529,74 +2633,74 @@ __metadata: languageName: node linkType: hard -"@next/eslint-plugin-next@npm:14.0.4": - version: 14.0.4 - resolution: "@next/eslint-plugin-next@npm:14.0.4" +"@next/eslint-plugin-next@npm:14.2.4": + version: 14.2.4 + resolution: "@next/eslint-plugin-next@npm:14.2.4" dependencies: - glob: 7.1.7 - checksum: 62e353227cdd1b47e35c3eb0aaac6d5160edaa2822ce23439459546375e841c2204abe66e3e6eded08c41e50ec467221df855b903f03378dc84982b73ac00e98 + glob: 10.3.10 + checksum: 65929cea46c252490ff2deb9bc57e2e1fab9baf02ece1af043dfd3b3ac58cb12ea7c3adbed8687d2a6c2938c1175338a389a695fe9d072712c77a21b55ed29f6 languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-darwin-arm64@npm:14.0.4" +"@next/swc-darwin-arm64@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-darwin-arm64@npm:14.2.4" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-darwin-x64@npm:14.0.4" +"@next/swc-darwin-x64@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-darwin-x64@npm:14.2.4" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-arm64-gnu@npm:14.0.4" +"@next/swc-linux-arm64-gnu@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-linux-arm64-gnu@npm:14.2.4" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-arm64-musl@npm:14.0.4" +"@next/swc-linux-arm64-musl@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-linux-arm64-musl@npm:14.2.4" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-x64-gnu@npm:14.0.4" +"@next/swc-linux-x64-gnu@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-linux-x64-gnu@npm:14.2.4" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-linux-x64-musl@npm:14.0.4" +"@next/swc-linux-x64-musl@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-linux-x64-musl@npm:14.2.4" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-win32-arm64-msvc@npm:14.0.4" +"@next/swc-win32-arm64-msvc@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-win32-arm64-msvc@npm:14.2.4" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-win32-ia32-msvc@npm:14.0.4" +"@next/swc-win32-ia32-msvc@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-win32-ia32-msvc@npm:14.2.4" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:14.0.4": - version: 14.0.4 - resolution: "@next/swc-win32-x64-msvc@npm:14.0.4" +"@next/swc-win32-x64-msvc@npm:14.2.4": + version: 14.2.4 + resolution: "@next/swc-win32-x64-msvc@npm:14.2.4" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2629,21 +2733,21 @@ __metadata: linkType: hard "@npmcli/agent@npm:^2.0.0": - version: 2.2.0 - resolution: "@npmcli/agent@npm:2.2.0" + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: ^7.1.0 http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.1 lru-cache: ^10.0.1 - socks-proxy-agent: ^8.0.1 - checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + socks-proxy-agent: ^8.0.3 + checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 languageName: node linkType: hard "@npmcli/arborist@npm:^6.5.0": - version: 6.5.0 - resolution: "@npmcli/arborist@npm:6.5.0" + version: 6.5.1 + resolution: "@npmcli/arborist@npm:6.5.1" dependencies: "@isaacs/string-locale-compare": ^1.1.0 "@npmcli/fs": ^3.1.0 @@ -2653,7 +2757,7 @@ __metadata: "@npmcli/name-from-folder": ^2.0.0 "@npmcli/node-gyp": ^3.0.0 "@npmcli/package-json": ^4.0.0 - "@npmcli/query": ^3.0.0 + "@npmcli/query": ^3.1.0 "@npmcli/run-script": ^6.0.0 bin-links: ^4.0.1 cacache: ^17.0.4 @@ -2680,32 +2784,32 @@ __metadata: walk-up-path: ^3.0.1 bin: arborist: bin/index.js - checksum: d389ecd5a63eeaf2d870259a1871d01610b594096b770ee2a09af1656333db04d66eeae1f5007c16de86d253ceea4fb0081b1cc6da8d3cb9f7f337a2a41f85b2 + checksum: 9d8dce58839d892ed8d72819acbe1701b07aeaddc23e5ee7634d5cd0781eccc77d8132c159b3dd7e12e862395acd2a12f104ee91526744f060e08d771c19dcd3 languageName: node linkType: hard "@npmcli/config@npm:^6.4.0": - version: 6.4.0 - resolution: "@npmcli/config@npm:6.4.0" + version: 6.4.1 + resolution: "@npmcli/config@npm:6.4.1" dependencies: "@npmcli/map-workspaces": ^3.0.2 - ci-info: ^3.8.0 + ci-info: ^4.0.0 ini: ^4.1.0 nopt: ^7.0.0 proc-log: ^3.0.0 read-package-json-fast: ^3.0.2 semver: ^7.3.5 walk-up-path: ^3.0.1 - checksum: c17c24b6bba18025f1d061c06a30eb80204568ae56600c21a47683a63280914062635d0e219362675ddab61cbc19bd07da05d30b9b83130f7674e773816e8dd6 + checksum: 0036cf05d8c9fe373c33e7b35724099e6dc356255e7ef27a161e9efa53f51b0ddeb70b4452f3de9bbc48a28d78312856852941950838da8da4bb23bbb9f950a2 languageName: node linkType: hard "@npmcli/disparity-colors@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/disparity-colors@npm:3.0.0" + version: 3.0.1 + resolution: "@npmcli/disparity-colors@npm:3.0.1" dependencies: ansi-styles: ^4.3.0 - checksum: 49320c6927b8e02a0eb006cfc9f5978370ae79ffa2b0da3b3d0ff2e9ef487501ebdec959dadc1e6f2725e16e27f9ea08f081a3af5126376f6f5b1caf6a1da0ce + checksum: bf24e2251180954568d7eb13f5b94900e390cca5603b1c98a39a439100cce33dbd9000135909195f45e3f0c7088ca79f2c2e298615f3c2f8cfc02ade87f765c3 languageName: node linkType: hard @@ -2720,11 +2824,11 @@ __metadata: linkType: hard "@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" dependencies: semver: ^7.3.5 - checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e + checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 languageName: node linkType: hard @@ -2745,26 +2849,26 @@ __metadata: linkType: hard "@npmcli/installed-package-contents@npm:^2.0.1, @npmcli/installed-package-contents@npm:^2.0.2": - version: 2.0.2 - resolution: "@npmcli/installed-package-contents@npm:2.0.2" + version: 2.1.0 + resolution: "@npmcli/installed-package-contents@npm:2.1.0" dependencies: npm-bundled: ^3.0.0 npm-normalize-package-bin: ^3.0.0 bin: - installed-package-contents: lib/index.js - checksum: 60789d5ed209ee5df479232f62d9d38ecec36e95701cae88320b828b8651351b32d7b47d16d4c36cc7ce5000db4bf1f3e6981bed6381bdc5687ff4bc0795682d + installed-package-contents: bin/index.js + checksum: d0f307e0c971a4ffaea44d4f38d53b57e19222413f338bab26d4321c4a7b9098318d74719dd1f8747a6de0575ac0ba29aeb388edf6599ac8299506947f53ffb6 languageName: node linkType: hard "@npmcli/map-workspaces@npm:^3.0.2, @npmcli/map-workspaces@npm:^3.0.4": - version: 3.0.4 - resolution: "@npmcli/map-workspaces@npm:3.0.4" + version: 3.0.6 + resolution: "@npmcli/map-workspaces@npm:3.0.6" dependencies: "@npmcli/name-from-folder": ^2.0.0 glob: ^10.2.2 minimatch: ^9.0.0 read-package-json-fast: ^3.0.0 - checksum: 99607dbc502b16d0ce7a47a81ccc496b3f5ed10df4e61e61a505929de12c356092996044174ae0cfd6d8cc177ef3b597eef4987b674fc0c5a306d3a8cc1fe91a + checksum: bdb09ee1d044bb9b2857d9e2d7ca82f40783a8549b5a7e150e25f874ee354cdbc8109ad7c3df42ec412f7057d95baa05920c4d361c868a93a42146b8e4390d3d languageName: node linkType: hard @@ -2828,12 +2932,12 @@ __metadata: languageName: node linkType: hard -"@npmcli/query@npm:^3.0.0": - version: 3.0.1 - resolution: "@npmcli/query@npm:3.0.1" +"@npmcli/query@npm:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/query@npm:3.1.0" dependencies: postcss-selector-parser: ^6.0.10 - checksum: b169b9c9a37c5a6e68d61604c7e3175ebdefbc3a77a8981326eaa8fa89cf4044fc6a87bd0fdbe5d096eda2f765aff1477924b55f4e23f64b3143dd1d9004eead + checksum: 33c018bfcc6d64593e7969847d0442beab4e8a42b6c9f932237c9fd135c95ab55de5c4b5d5d66302dd9fc3c748bc4ead780d3595e5d586fedf9859ed6b5f2744 languageName: node linkType: hard @@ -2858,56 +2962,63 @@ __metadata: linkType: hard "@octokit/core@npm:^5.0.0": - version: 5.0.2 - resolution: "@octokit/core@npm:5.0.2" + version: 5.2.0 + resolution: "@octokit/core@npm:5.2.0" dependencies: "@octokit/auth-token": ^4.0.0 - "@octokit/graphql": ^7.0.0 - "@octokit/request": ^8.0.2 - "@octokit/request-error": ^5.0.0 - "@octokit/types": ^12.0.0 + "@octokit/graphql": ^7.1.0 + "@octokit/request": ^8.3.1 + "@octokit/request-error": ^5.1.0 + "@octokit/types": ^13.0.0 before-after-hook: ^2.2.0 universal-user-agent: ^6.0.0 - checksum: 9ce060d61577f6805901ae5c33b2764a441db119ae0cca09104adf37b119cce68b656220de56c0c5004c9c9c1c892a7fdfbe9c0b1f5e398cb359dfd39c57eca8 + checksum: 57d5f02b759b569323dcb76cc72bf94ea7d0de58638c118ee14ec3e37d303c505893137dd72918328794844f35c74b3cd16999319c4b40d410a310d44a9b7566 languageName: node linkType: hard -"@octokit/endpoint@npm:^9.0.0": - version: 9.0.4 - resolution: "@octokit/endpoint@npm:9.0.4" +"@octokit/endpoint@npm:^9.0.1": + version: 9.0.5 + resolution: "@octokit/endpoint@npm:9.0.5" dependencies: - "@octokit/types": ^12.0.0 + "@octokit/types": ^13.1.0 universal-user-agent: ^6.0.0 - checksum: ed1b64a448f478e5951a043ef816d634a5a1f584519cbf2f374ceac058f82a16e52f078f156aa8b8cbcab7b0590348d94294fc83c9b4eebd42a820a5f10db81c + checksum: d5cc2df9bd4603844c163eea05eec89c677cfe699c6f065fe86b83123e34554ec16d429e8142dec1e2b4cf56591ef0ce5b1763f250c87bc8e7bf6c74ba59ae82 languageName: node linkType: hard -"@octokit/graphql@npm:^7.0.0": - version: 7.0.2 - resolution: "@octokit/graphql@npm:7.0.2" +"@octokit/graphql@npm:^7.1.0": + version: 7.1.0 + resolution: "@octokit/graphql@npm:7.1.0" dependencies: - "@octokit/request": ^8.0.1 - "@octokit/types": ^12.0.0 + "@octokit/request": ^8.3.0 + "@octokit/types": ^13.0.0 universal-user-agent: ^6.0.0 - checksum: 05a752c4c2d84fc2900d8e32e1c2d1ee98a5a14349e651cb1109d0741e821e7417a048b1bb40918534ed90a472314aabbda35688868016f248098925f82a3bfa + checksum: 7b2706796e0269fc033ed149ea211117bcacf53115fd142c1eeafc06ebc5b6290e4e48c03d6276c210d72e3695e8598f83caac556cd00714fc1f8e4707d77448 languageName: node linkType: hard -"@octokit/openapi-types@npm:^19.1.0": - version: 19.1.0 - resolution: "@octokit/openapi-types@npm:19.1.0" - checksum: 9d1b188741609a9832b964df2bc337ee77c1fc89d5f686faebb743c7cb27721e214180d623ee28227427b4c43719b79ee4890e338a709b78a9f249a7c369ac3e +"@octokit/openapi-types@npm:^20.0.0": + version: 20.0.0 + resolution: "@octokit/openapi-types@npm:20.0.0" + checksum: 23ff7613750f8b5790a0cbed5a2048728a7909e50d726932831044908357a932c7fc0613fb7b86430a49d31b3d03a180632ea5dd936535bfbc1176391a199e96 + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^22.2.0": + version: 22.2.0 + resolution: "@octokit/openapi-types@npm:22.2.0" + checksum: eca41feac2b83298e0d95e253ac1c5b6d65155ac57f65c5fd8d4a485d9728922d85ff4bee0e815a1f3a5421311db092bdb6da9d6104a1b1843d8b274bcad9630 languageName: node linkType: hard "@octokit/plugin-paginate-rest@npm:^9.0.0": - version: 9.1.5 - resolution: "@octokit/plugin-paginate-rest@npm:9.1.5" + version: 9.2.1 + resolution: "@octokit/plugin-paginate-rest@npm:9.2.1" dependencies: - "@octokit/types": ^12.4.0 + "@octokit/types": ^12.6.0 peerDependencies: - "@octokit/core": ">=5" - checksum: ee5bc62e3175b61fdd3e65cc26410e1130931e729591003b302167cb02d0cec0746fd58220800d07de179e36077b9d675c794d0859457b701a7692b9fcde49a0 + "@octokit/core": 5 + checksum: 554ad17a7dcfd7028e321ffcae233f8ae7975569084f19d9b6217b47fb182e2604145108de7a9029777e6dc976b27b2dd7387e2e47a77532a72e6c195880576d languageName: node linkType: hard @@ -2925,46 +3036,55 @@ __metadata: linkType: hard "@octokit/plugin-throttling@npm:^8.0.0": - version: 8.1.3 - resolution: "@octokit/plugin-throttling@npm:8.1.3" + version: 8.2.0 + resolution: "@octokit/plugin-throttling@npm:8.2.0" dependencies: "@octokit/types": ^12.2.0 bottleneck: ^2.15.3 peerDependencies: "@octokit/core": ^5.0.0 - checksum: 98963ef2eab825015702b1ca1ef4ccbda0c009242e93001144e51014d3b53d3ecb1282b67488680c7f5f4e805d0c3af4020ad673079fff92c6353f04903a9a64 + checksum: 12c357175783bcd0feea454ece57f033928948a0555dc97c79675b56d2cc79043d2a5e28a7554d3531f1de13583634df3b48fb9609f79e8bb3adad92820bd807 languageName: node linkType: hard -"@octokit/request-error@npm:^5.0.0": - version: 5.0.1 - resolution: "@octokit/request-error@npm:5.0.1" +"@octokit/request-error@npm:^5.0.0, @octokit/request-error@npm:^5.1.0": + version: 5.1.0 + resolution: "@octokit/request-error@npm:5.1.0" dependencies: - "@octokit/types": ^12.0.0 + "@octokit/types": ^13.1.0 deprecation: ^2.0.0 once: ^1.4.0 - checksum: a681341e43b4da7a8acb19e1a6ba0355b1af146fa0191f2554a98950cf85f898af6ae3ab0b0287d6c871f5465ec57cb38363b96b5019f9f77ba6f30eca39ede5 + checksum: 2cdbb8e44072323b5e1c8c385727af6700e3e492d55bc1e8d0549c4a3d9026914f915866323d371b1f1772326d6e902341c872679cc05c417ffc15cadf5f4a4e languageName: node linkType: hard -"@octokit/request@npm:^8.0.1, @octokit/request@npm:^8.0.2": - version: 8.1.6 - resolution: "@octokit/request@npm:8.1.6" +"@octokit/request@npm:^8.3.0, @octokit/request@npm:^8.3.1": + version: 8.4.0 + resolution: "@octokit/request@npm:8.4.0" dependencies: - "@octokit/endpoint": ^9.0.0 - "@octokit/request-error": ^5.0.0 - "@octokit/types": ^12.0.0 + "@octokit/endpoint": ^9.0.1 + "@octokit/request-error": ^5.1.0 + "@octokit/types": ^13.1.0 universal-user-agent: ^6.0.0 - checksum: df90204586ee7db5adf69c3007c5d9c0a866de488c9ba8756f98083208726ed360d5a541e68204c413fa10e6f17e171dc9868b18768b9799df0003bc84c59cf2 + checksum: 3d937e817a85c0adf447ab46b428ccd702c31b2091e47adec90583ec2242bd64666306fe8188628fb139aa4752e19400eb7652b0f5ca33cd9e77bbb2c60b202a + languageName: node + linkType: hard + +"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.2.0, @octokit/types@npm:^12.6.0": + version: 12.6.0 + resolution: "@octokit/types@npm:12.6.0" + dependencies: + "@octokit/openapi-types": ^20.0.0 + checksum: 850235f425584499a2266d5c585c1c2462ae11e25c650567142f3342cb9ce589c8c8fed87705811ca93271fd28c68e1fa77b88b67b97015d7b63d269fa46ed05 languageName: node linkType: hard -"@octokit/types@npm:^12.0.0, @octokit/types@npm:^12.2.0, @octokit/types@npm:^12.4.0": - version: 12.4.0 - resolution: "@octokit/types@npm:12.4.0" +"@octokit/types@npm:^13.0.0, @octokit/types@npm:^13.1.0": + version: 13.5.0 + resolution: "@octokit/types@npm:13.5.0" dependencies: - "@octokit/openapi-types": ^19.1.0 - checksum: 17bca450efc5433f14e1f93a24232316a0fb490aec8d886c3a430e853f10a74e6664751a44e0e199336b23c20658c4afcb3590e422ba7c155c2cb31f433ebbb7 + "@octokit/openapi-types": ^22.2.0 + checksum: 8e92f2b145b3c28a35312f93714245824a7b6b7353caa88edfdc85fc2ed4108321ed0c3988001ea53449fbb212febe0e8e9582744e85c3574dabe9d0441af5a0 languageName: node linkType: hard @@ -3052,9 +3172,9 @@ __metadata: languageName: node linkType: hard -"@rc-component/trigger@npm:^1.17.0": - version: 1.18.2 - resolution: "@rc-component/trigger@npm:1.18.2" +"@rc-component/trigger@npm:^2.0.0": + version: 2.2.0 + resolution: "@rc-component/trigger@npm:2.2.0" dependencies: "@babel/runtime": ^7.23.2 "@rc-component/portal": ^1.1.0 @@ -3065,7 +3185,7 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: a1ecc787919c614d4cdd0ec140caf1685de4570da159248701edf1cb379f5cebf2e66f0a9ed7d6542b522c2a92fcdb72ec5dfb9a34a00599278381f598a6f7fb + checksum: 55cb5b8b9456507a41977999b84db9247f3b0e50bc3fadc1d234187df630d208779c5c9c45d0c152f29b968740d6fa043e9496255b7aa7cc3e18347a325420e4 languageName: node linkType: hard @@ -3104,101 +3224,122 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.13.0" +"@rollup/rollup-android-arm-eabi@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.18.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-android-arm64@npm:4.13.0" +"@rollup/rollup-android-arm64@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-android-arm64@npm:4.18.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-darwin-arm64@npm:4.13.0" +"@rollup/rollup-darwin-arm64@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.18.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-darwin-x64@npm:4.13.0" +"@rollup/rollup-darwin-x64@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.18.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.13.0" - conditions: os=linux & cpu=arm +"@rollup/rollup-linux-arm-gnueabihf@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.18.0" + conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.13.0" +"@rollup/rollup-linux-arm64-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.18.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.13.0" +"@rollup/rollup-linux-arm64-musl@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.18.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.13.0" +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.18.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.13.0" +"@rollup/rollup-linux-s390x-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.18.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.18.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.13.0" +"@rollup/rollup-linux-x64-musl@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.18.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.13.0" +"@rollup/rollup-win32-arm64-msvc@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.18.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.13.0" +"@rollup/rollup-win32-ia32-msvc@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.18.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.13.0" +"@rollup/rollup-win32-x64-msvc@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.18.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@rushstack/eslint-patch@npm:^1.3.3": - version: 1.6.1 - resolution: "@rushstack/eslint-patch@npm:1.6.1" - checksum: d0c0fcc430dae71d9d929e593844aeaec8d326b1d6c27f18059e22dad486d8df43d6f0206b2021a0df789baf514642355bd86eae7a42c457b7b2f48a29bb0f53 + version: 1.10.3 + resolution: "@rushstack/eslint-patch@npm:1.10.3" + checksum: 1042779367ee102576a3c132f052d718d7111fee9f815758a72b21e8145620f7d3403c14fcde3b4cfa1cbc14b08b8519151ff77d0f353bf647f0a0a16eafdef5 languageName: node linkType: hard @@ -3357,45 +3498,59 @@ __metadata: languageName: node linkType: hard -"@sentry-internal/feedback@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry-internal/feedback@npm:7.91.0" +"@sentry-internal/feedback@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry-internal/feedback@npm:7.117.0" + dependencies: + "@sentry/core": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: 937c1a59723881ac090a8b12669a6f2264d04c7e50ba73a802031a68187a3799cdc7d41f8a5f0023eee3321bce145141f385ee353a880f17f028e45b57e57044 + languageName: node + linkType: hard + +"@sentry-internal/replay-canvas@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry-internal/replay-canvas@npm:7.117.0" dependencies: - "@sentry/core": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - checksum: 91ae9095e6c8193f9fef7bcec902c53a9ba14e1dd755a22ec3e129264b4155a36aef4acd7b71d7de54441929099c0d8de941d5489c9e1c32263f3421fc1c9ef3 + "@sentry/core": 7.117.0 + "@sentry/replay": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: d84e9fa4d777a00b83d5e60aa4a9ca5a74768c3eb8e2aadcec0adc0379900103027a23cd3c228d3e8adca90f45b6c3a0713f051258aaf5ac32656f887ba26350 languageName: node linkType: hard -"@sentry-internal/tracing@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry-internal/tracing@npm:7.91.0" +"@sentry-internal/tracing@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry-internal/tracing@npm:7.117.0" dependencies: - "@sentry/core": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - checksum: 2097dedbaa7a138fe7125b60545fcc115d9de0adaa97f35a1fd9ea28a30b915c6a0d9d1a69c6d7f7616708241004152676752178efa15e39eb971732457acae5 + "@sentry/core": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: 3a4b5b4ebfa8da73e324aef2ed20921a840e88b3a1b949c8f092b6cf73c6e7dcb99bb8c47bf6ac56101b53ed959597c29f22a4618fd5d93c05e04c3841ebe256 languageName: node linkType: hard -"@sentry/browser@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry/browser@npm:7.91.0" +"@sentry/browser@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry/browser@npm:7.117.0" dependencies: - "@sentry-internal/feedback": 7.91.0 - "@sentry-internal/tracing": 7.91.0 - "@sentry/core": 7.91.0 - "@sentry/replay": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - checksum: 5b8134374575bcefc73910e99471f4bde442ba800b7fa2d02b0633d795707d0fa74a918212aa7d093bc81e0cc3865aac2fe3e6be5e721001036f588c8ad30695 + "@sentry-internal/feedback": 7.117.0 + "@sentry-internal/replay-canvas": 7.117.0 + "@sentry-internal/tracing": 7.117.0 + "@sentry/core": 7.117.0 + "@sentry/integrations": 7.117.0 + "@sentry/replay": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: 161113058e7c48333d9bbdf278d799d3da355a5b2e77ce12bf796bfc40cd5e099b8569df5372e0d3f6d508e516def768e3251add97a9ddfa007ddb60f0873566 languageName: node linkType: hard "@sentry/cli@npm:^1.77.1": - version: 1.77.1 - resolution: "@sentry/cli@npm:1.77.1" + version: 1.77.3 + resolution: "@sentry/cli@npm:1.77.3" dependencies: https-proxy-agent: ^5.0.0 mkdirp: ^0.5.5 @@ -3405,44 +3560,44 @@ __metadata: which: ^2.0.2 bin: sentry-cli: bin/sentry-cli - checksum: 8b2604ece002ad5124af4a607bd5c208cde582164315b7028cdf82864eb67de3dfdab99ecee93d36d698e85f05d3a8c8082368659c499f9a3f711b8f55dffc79 + checksum: 193a144c5b449d5c0ea709d7c5678da3f1daa15f31aefa7de40197ed1152fef7c2a0abe168ce2447f1cc2f6eed6fdbcdaa5f20dc4502f8987d656d3e5e87fe99 languageName: node linkType: hard -"@sentry/core@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry/core@npm:7.91.0" +"@sentry/core@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry/core@npm:7.117.0" dependencies: - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - checksum: 5a284c1b1f88ed8d642578cce293c91a0979f533db156fcccb8cae68d1d426a14730e6b06d993a69a1d640b988481c6451dcffe8812c6bc3e23fc8bce5c04dc0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: ef22d6d3d358cfae9cee6c1ef62bc425987dd7262089d78b80851b32a1b6ad50282cbe83b7d9c16d411fd5861065775b69bc989656b311d4692a207d8fda8e1c languageName: node linkType: hard -"@sentry/integrations@npm:7.91.0, @sentry/integrations@npm:^7.72.0, @sentry/integrations@npm:^7.73.0": - version: 7.91.0 - resolution: "@sentry/integrations@npm:7.91.0" +"@sentry/integrations@npm:7.117.0, @sentry/integrations@npm:^7.72.0, @sentry/integrations@npm:^7.73.0": + version: 7.117.0 + resolution: "@sentry/integrations@npm:7.117.0" dependencies: - "@sentry/core": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 + "@sentry/core": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 localforage: ^1.8.1 - checksum: ab7b6f129892d9146215660c76d0260eb2d48872329611860cdb1051a4d12e9ba393b216183473f9ca1be1cb89fcfe7a337ac6fe80b0aeca09faae297d909fc6 + checksum: 5b1ba3fb6e12ea2b79cbd2f2ce592621abfc37bf9809e6fcd2b1d1cfa4c589d40534747ef9bb64ed6a342f847130c29fc737a7297d6197a63e0228091bdf96cb languageName: node linkType: hard "@sentry/nextjs@npm:^7.73.0": - version: 7.91.0 - resolution: "@sentry/nextjs@npm:7.91.0" + version: 7.117.0 + resolution: "@sentry/nextjs@npm:7.117.0" dependencies: "@rollup/plugin-commonjs": 24.0.0 - "@sentry/core": 7.91.0 - "@sentry/integrations": 7.91.0 - "@sentry/node": 7.91.0 - "@sentry/react": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - "@sentry/vercel-edge": 7.91.0 + "@sentry/core": 7.117.0 + "@sentry/integrations": 7.117.0 + "@sentry/node": 7.117.0 + "@sentry/react": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + "@sentry/vercel-edge": 7.117.0 "@sentry/webpack-plugin": 1.21.0 chalk: 3.0.0 resolve: 1.22.8 @@ -3455,83 +3610,85 @@ __metadata: peerDependenciesMeta: webpack: optional: true - checksum: e7aba85615d74375dca2aa8709862b6f37e2a6a1fe6f9e2b7d9461b26a002825b377d41da3b5450c7ee7ee54e15b19072b4bb7d5b36441a89c419fd854cacf2d + checksum: 8805bb605e61c54d8462a323fd578593c5845b822995cd5a85a3161dd93f494cdc8938a1b62774b42e4251b24a270ef68014220c51bc7586491d3a209589549c languageName: node linkType: hard -"@sentry/node@npm:7.91.0, @sentry/node@npm:^7.60.0, @sentry/node@npm:^7.72.0": - version: 7.91.0 - resolution: "@sentry/node@npm:7.91.0" +"@sentry/node@npm:7.117.0, @sentry/node@npm:^7.60.0, @sentry/node@npm:^7.72.0": + version: 7.117.0 + resolution: "@sentry/node@npm:7.117.0" dependencies: - "@sentry-internal/tracing": 7.91.0 - "@sentry/core": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - https-proxy-agent: ^5.0.0 - checksum: 49971e47aa29b8232f5c13d613dbe9a651da11146813b88b4a8038f7f3b8ae44d98603e784f47c616d303e77d3f22257cfd1ac86f0a8d960f89ba0d51a69d42a + "@sentry-internal/tracing": 7.117.0 + "@sentry/core": 7.117.0 + "@sentry/integrations": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: ceed301f26353d224d9e345821ff165bb360f430f7bbbaa6a9a6af9c2b27d62d2c6542f9e1bbdd512331577859049afc6d8d22fb5d70e466914e847ed06337cf languageName: node linkType: hard -"@sentry/react@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry/react@npm:7.91.0" +"@sentry/react@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry/react@npm:7.117.0" dependencies: - "@sentry/browser": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 + "@sentry/browser": 7.117.0 + "@sentry/core": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 hoist-non-react-statics: ^3.3.2 peerDependencies: react: 15.x || 16.x || 17.x || 18.x - checksum: 75d2a9d05e07abf4c0da839677221a24954ae9883cea5521319de5f4e6067e2ff84b8ef82ee6d20707989f970329856f3918bfba55fc486bc9457f5c50e0d4e1 + checksum: b57c0cafd7756fe7a27b757920a930b15bdd88dcc227a68d3cf86d086a174adb89630b31d139d475d5cbfc95dc850681e7dfc8f9f4cd1f766a0fc08e4624bf9f languageName: node linkType: hard -"@sentry/replay@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry/replay@npm:7.91.0" +"@sentry/replay@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry/replay@npm:7.117.0" dependencies: - "@sentry-internal/tracing": 7.91.0 - "@sentry/core": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - checksum: 66cd1217b1a179f413b4ff40f55683628ffc02a638b176d97d6bf081466519eff4e823fa35741ec608f34066c2cf7a3663b681752f161389a951950ac5b8c5d2 + "@sentry-internal/tracing": 7.117.0 + "@sentry/core": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: de9b8783c1670d652934931d08fd0e0797d476493b36aeda4f945d184bb2a45df570dbd11e4381ae7369b91c758bfb5703fee2dd2ef4ce1d8b5d59e1d08a81b1 languageName: node linkType: hard "@sentry/tracing@npm:^7.60.0": - version: 7.91.0 - resolution: "@sentry/tracing@npm:7.91.0" + version: 7.117.0 + resolution: "@sentry/tracing@npm:7.117.0" dependencies: - "@sentry-internal/tracing": 7.91.0 - checksum: 86d7e480fcd357d4144d3e515af57c9293f2f969f7fd4b836fd06fc5cd21eb5758fb1e7ea35b2ac70a6fd2b8a0a4ce9b671b2bf5cc61322a8a227b66a91d5614 + "@sentry-internal/tracing": 7.117.0 + checksum: c3c65701e48d585ca21f7f002f6a15647d23720fdc1a6cc37e04c3e6876f0704ac9b1ded408e1a1cbfd9c1dbcc02036aca1e9d063582af92bf20afd01e9f09e9 languageName: node linkType: hard -"@sentry/types@npm:7.91.0, @sentry/types@npm:^7.72.0": - version: 7.91.0 - resolution: "@sentry/types@npm:7.91.0" - checksum: a0b8853b1257e860e823d4907fbe53914083891fe82699bccf9669342575b01ff663350d300784a0987e56adeb6c9902b1c3012cb957015b56570676c55bf291 +"@sentry/types@npm:7.117.0, @sentry/types@npm:^7.72.0": + version: 7.117.0 + resolution: "@sentry/types@npm:7.117.0" + checksum: f3eabf921ecbe1e89c5dc50fd5f52340484ae710333718a6e027f58462bee552d22a70ff50e2a8b9924f935a3b86e3ec4aca20ab3bc3fbee1f77c3a6d49255df languageName: node linkType: hard -"@sentry/utils@npm:7.91.0, @sentry/utils@npm:^7.60.0": - version: 7.91.0 - resolution: "@sentry/utils@npm:7.91.0" +"@sentry/utils@npm:7.117.0, @sentry/utils@npm:^7.60.0": + version: 7.117.0 + resolution: "@sentry/utils@npm:7.117.0" dependencies: - "@sentry/types": 7.91.0 - checksum: 79a9ae4193fc42c2fff8b7808958170164966410149101526da923233cef5f741ab8953842544e7481155e0f3a828ebf2a6b040f30d03945b603377036eece58 + "@sentry/types": 7.117.0 + checksum: d8cf0db1a1b572ed0fa673aa29864bfb47ffa03ddfba13da253b018f5d1fb16b2d5b7e0e302194af30881c1fec2de5896df60a71bd9507b009f9736b24b89b7d languageName: node linkType: hard -"@sentry/vercel-edge@npm:7.91.0": - version: 7.91.0 - resolution: "@sentry/vercel-edge@npm:7.91.0" +"@sentry/vercel-edge@npm:7.117.0": + version: 7.117.0 + resolution: "@sentry/vercel-edge@npm:7.117.0" dependencies: - "@sentry-internal/tracing": 7.91.0 - "@sentry/core": 7.91.0 - "@sentry/types": 7.91.0 - "@sentry/utils": 7.91.0 - checksum: 8a130f3d11f26a10c54c622554289543681f40d8ff76cefd9043a73ead3d68078e1eebdd05423831742ec874ab7cc39e2e66e022afc48e9c40942e42da3bb544 + "@sentry-internal/tracing": 7.117.0 + "@sentry/core": 7.117.0 + "@sentry/integrations": 7.117.0 + "@sentry/types": 7.117.0 + "@sentry/utils": 7.117.0 + checksum: 6447c5c64135c3a19ea75899f6ba8b4c483d1c4acca419756e03d52b000b83b65bad3862aa6a3e2e9c9244dd74630a6909e023ea9fbedbebd13b58ba075e0972 languageName: node linkType: hard @@ -3545,12 +3702,12 @@ __metadata: languageName: node linkType: hard -"@sideway/address@npm:^4.1.3": - version: 4.1.4 - resolution: "@sideway/address@npm:4.1.4" +"@sideway/address@npm:^4.1.5": + version: 4.1.5 + resolution: "@sideway/address@npm:4.1.5" dependencies: "@hapi/hoek": ^9.0.0 - checksum: b9fca2a93ac2c975ba12e0a6d97853832fb1f4fb02393015e012b47fa916a75ca95102d77214b2a29a2784740df2407951af8c5dde054824c65577fd293c4cdb + checksum: 3e3ea0f00b4765d86509282290368a4a5fd39a7995fdc6de42116ca19a96120858e56c2c995081def06e1c53e1f8bccc7d013f6326602bec9d56b72ee2772b9d languageName: node linkType: hard @@ -3626,110 +3783,110 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/merge-streams@npm:^1.0.0": - version: 1.0.0 - resolution: "@sindresorhus/merge-streams@npm:1.0.0" - checksum: 453c2a28164113a5ec4fd23ba636e291a4112f6ee9e91cd5476b9a96e0fc9ee5ff40d405fe81bbf284c9773b7ed718a3a0f31df7895a0efd413b1f9775d154fe +"@sindresorhus/merge-streams@npm:^2.1.0": + version: 2.3.0 + resolution: "@sindresorhus/merge-streams@npm:2.3.0" + checksum: e989d53dee68d7e49b4ac02ae49178d561c461144cea83f66fa91ff012d981ad0ad2340cbd13f2fdb57989197f5c987ca22a74eb56478626f04e79df84291159 languageName: node linkType: hard "@socialgouv/matomo-next@npm:^1.8.0": - version: 1.8.0 - resolution: "@socialgouv/matomo-next@npm:1.8.0" + version: 1.9.0 + resolution: "@socialgouv/matomo-next@npm:1.9.0" peerDependencies: next: ">= 9.5.5" - checksum: 810fc35234ceb417c6ceecb125d048c77458b6c3b6890fd3271eaa13c2cc2e77a84f4debc92e3a1ac84c5eea02cf09c3e788efb850afc8d63b341a64e0b41071 + checksum: 5f2a15a99f38b36bf3ab9c767f12a6df3c53740e38aa1db6e05168fdcefbcf90a37fe7c4e424ce333a2385f60b0bca59b5857136fab128b30476b3a6bb2a5c8a languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-darwin-arm64@npm:1.3.102" +"@swc/core-darwin-arm64@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-darwin-arm64@npm:1.6.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-darwin-x64@npm:1.3.102" +"@swc/core-darwin-x64@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-darwin-x64@npm:1.6.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.102" +"@swc/core-linux-arm-gnueabihf@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.6.3" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.102" +"@swc/core-linux-arm64-gnu@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-linux-arm64-gnu@npm:1.6.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.102" +"@swc/core-linux-arm64-musl@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-linux-arm64-musl@npm:1.6.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.102" +"@swc/core-linux-x64-gnu@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-linux-x64-gnu@npm:1.6.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-linux-x64-musl@npm:1.3.102" +"@swc/core-linux-x64-musl@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-linux-x64-musl@npm:1.6.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.102" +"@swc/core-win32-arm64-msvc@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-win32-arm64-msvc@npm:1.6.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.102" +"@swc/core-win32-ia32-msvc@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-win32-ia32-msvc@npm:1.6.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.102": - version: 1.3.102 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.102" +"@swc/core-win32-x64-msvc@npm:1.6.3": + version: 1.6.3 + resolution: "@swc/core-win32-x64-msvc@npm:1.6.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.90": - version: 1.3.102 - resolution: "@swc/core@npm:1.3.102" - dependencies: - "@swc/core-darwin-arm64": 1.3.102 - "@swc/core-darwin-x64": 1.3.102 - "@swc/core-linux-arm-gnueabihf": 1.3.102 - "@swc/core-linux-arm64-gnu": 1.3.102 - "@swc/core-linux-arm64-musl": 1.3.102 - "@swc/core-linux-x64-gnu": 1.3.102 - "@swc/core-linux-x64-musl": 1.3.102 - "@swc/core-win32-arm64-msvc": 1.3.102 - "@swc/core-win32-ia32-msvc": 1.3.102 - "@swc/core-win32-x64-msvc": 1.3.102 - "@swc/counter": ^0.1.1 - "@swc/types": ^0.1.5 + version: 1.6.3 + resolution: "@swc/core@npm:1.6.3" + dependencies: + "@swc/core-darwin-arm64": 1.6.3 + "@swc/core-darwin-x64": 1.6.3 + "@swc/core-linux-arm-gnueabihf": 1.6.3 + "@swc/core-linux-arm64-gnu": 1.6.3 + "@swc/core-linux-arm64-musl": 1.6.3 + "@swc/core-linux-x64-gnu": 1.6.3 + "@swc/core-linux-x64-musl": 1.6.3 + "@swc/core-win32-arm64-msvc": 1.6.3 + "@swc/core-win32-ia32-msvc": 1.6.3 + "@swc/core-win32-x64-msvc": 1.6.3 + "@swc/counter": ^0.1.3 + "@swc/types": ^0.1.8 peerDependencies: - "@swc/helpers": ^0.5.0 + "@swc/helpers": "*" dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -3754,30 +3911,33 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 45c0edb06f87a811e28fb3ed587fbe6b7ca67ff2440fe15666d43729788903a4af61e3b57842aecc0b2b70e3c9981b698d8233746ba94dfb5a19e1c62eea33ad + checksum: c632e545ea494480b8273d0adc0cac5986576a3e9eda95c550c06e402f924d9948fe71bff14809455da7ff86f043a7444a71bff2e0ff05fad76689f69067057e languageName: node linkType: hard -"@swc/counter@npm:^0.1.1": - version: 0.1.2 - resolution: "@swc/counter@npm:0.1.2" - checksum: 8427c594f1f0cf44b83885e9c8fe1e370c9db44ae96e07a37c117a6260ee97797d0709483efbcc244e77bac578690215f45b23254c4cd8a70fb25ddbb50bf33e +"@swc/counter@npm:^0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard -"@swc/helpers@npm:0.5.2": - version: 0.5.2 - resolution: "@swc/helpers@npm:0.5.2" +"@swc/helpers@npm:0.5.5": + version: 0.5.5 + resolution: "@swc/helpers@npm:0.5.5" dependencies: + "@swc/counter": ^0.1.3 tslib: ^2.4.0 - checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 + checksum: d4f207b191e54b29460804ddf2984ba6ece1d679a0b2f6a9c765dcf27bba92c5769e7965668a4546fb9f1021eaf0ff9be4bf5c235ce12adcd65acdfe77187d11 languageName: node linkType: hard -"@swc/types@npm:^0.1.5": - version: 0.1.5 - resolution: "@swc/types@npm:0.1.5" - checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b +"@swc/types@npm:^0.1.8": + version: 0.1.8 + resolution: "@swc/types@npm:0.1.8" + dependencies: + "@swc/counter": ^0.1.3 + checksum: e564d0e37b0e28546973c6d50c7a179395912a97168d695cfe9cf1051199c8b828680cdafcb8d43948f76d3703873bafb88dfb5bc2dfe0596b4ad18fcaf90c80 languageName: node linkType: hard @@ -3837,9 +3997,9 @@ __metadata: linkType: hard "@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df + version: 1.0.11 + resolution: "@tsconfig/node10@npm:1.0.11" + checksum: 51fe47d55fe1b80ec35e6e5ed30a13665fd3a531945350aa74a14a1e82875fb60b350c2f2a5e72a64831b1b6bc02acb6760c30b3738b54954ec2dea82db7a267 languageName: node linkType: hard @@ -3931,15 +4091,6 @@ __metadata: languageName: node linkType: hard -"@types/bson@npm:*, @types/bson@npm:1.x || 4.0.x": - version: 4.0.5 - resolution: "@types/bson@npm:4.0.5" - dependencies: - "@types/node": "*" - checksum: f6c74a68eec836010170e7091399b45fe39e2f7724372441cc00a0fbd0b9f44d901688504174d558edbf220922fa0c7c52fbc4aa0f2136194fa713101b8f2ec9 - languageName: node - linkType: hard - "@types/bunyan@npm:^1.8.9": version: 1.8.11 resolution: "@types/bunyan@npm:1.8.11" @@ -4010,14 +4161,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.41 - resolution: "@types/express-serve-static-core@npm:4.17.41" + version: 4.19.3 + resolution: "@types/express-serve-static-core@npm:4.19.3" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 12750f6511dd870bbaccfb8208ad1e79361cf197b147f62a3bedc19ec642f3a0f9926ace96705f4bc88ec2ae56f61f7ca8c2438e6b22f5540842b5569c28a121 + checksum: fff38a7f43baeb6a62380682d39846c9d92047e0dce1737d76ebd944528619abc18addc4f0548bf43dbf4514090a1bd5140ba36695024656f941a87424b8ed7d languageName: node linkType: hard @@ -4080,7 +4231,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 @@ -4095,11 +4246,11 @@ __metadata: linkType: hard "@types/jsonwebtoken@npm:^9.0.3": - version: 9.0.5 - resolution: "@types/jsonwebtoken@npm:9.0.5" + version: 9.0.6 + resolution: "@types/jsonwebtoken@npm:9.0.6" dependencies: "@types/node": "*" - checksum: 07ab6fee602e5bd3fb5c6dfe4ec400769dc20f1d7fce901feecb4c3af5f5f08323b03ea55de3e49b1aa41e171a59008f6f4318738a735588c5268a63eba25337 + checksum: a568e7cb1c703bcb015eff8bf5996e276e748d2b39ddc47edf5ddccd1378f5792179c43302a1c803e47a54b0220f9ecaae445ec444d28bf81b88856f899e85b9 languageName: node linkType: hard @@ -4131,9 +4282,9 @@ __metadata: linkType: hard "@types/lodash@npm:*, @types/lodash@npm:^4.14.175": - version: 4.14.202 - resolution: "@types/lodash@npm:4.14.202" - checksum: a91acf3564a568c6f199912f3eb2c76c99c5a0d7e219394294213b3f2d54f672619f0fde4da22b29dc5d4c31457cd799acc2e5cb6bd90f9af04a1578483b6ff7 + version: 4.17.5 + resolution: "@types/lodash@npm:4.17.5" + checksum: 3c9bb15772509f0ecb40428531863dbc3f064f2bf34bbccc2ce2b2923c69fb0868aec7e357b1d97fd0d7f7e435a014ea5c1adef8a64715529887179c97a5a823 languageName: node linkType: hard @@ -4160,13 +4311,6 @@ __metadata: languageName: node linkType: hard -"@types/mime@npm:*": - version: 3.0.4 - resolution: "@types/mime@npm:3.0.4" - checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 - languageName: node - linkType: hard - "@types/mime@npm:^1": version: 1.3.5 resolution: "@types/mime@npm:1.3.5" @@ -4197,16 +4341,6 @@ __metadata: languageName: node linkType: hard -"@types/mongodb@npm:^3.5.27": - version: 3.6.20 - resolution: "@types/mongodb@npm:3.6.20" - dependencies: - "@types/bson": "*" - "@types/node": "*" - checksum: e5397ada2ed728997f7c3f5424e8c28f682a635488be967c9c18a5de27b1641cf28bb42bc12026ac6d475c457a880e27097e13c8120350ba13219f4ccc030656 - languageName: node - linkType: hard - "@types/netmask@npm:^2.0.3": version: 2.0.5 resolution: "@types/netmask@npm:2.0.5" @@ -4214,12 +4348,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.7.1": - version: 20.10.6 - resolution: "@types/node@npm:20.10.6" +"@types/node@npm:*, @types/node@npm:^20.12.12, @types/node@npm:^20.7.1": + version: 20.14.6 + resolution: "@types/node@npm:20.14.6" dependencies: undici-types: ~5.26.4 - checksum: ada40e4ccbda3697dca88f8d13f4c996c493be6fbc15f5f5d3b91096d56bd700786a2c148a92a2b4c5d1f133379e63f754a786b3aebfc6a7d09fc7ea16dc017b + checksum: f0ba22b181cfa799e090e5198621d8bf2b35f2c18ce880b8cdf88a69f9db5a4cc56627fe2dfeca44b6a55895c0abf03df04810cabd9509b9c9b752189d37aa1f languageName: node linkType: hard @@ -4248,11 +4382,11 @@ __metadata: linkType: hard "@types/nodemailer@npm:*, @types/nodemailer@npm:^6.4.11": - version: 6.4.14 - resolution: "@types/nodemailer@npm:6.4.14" + version: 6.4.15 + resolution: "@types/nodemailer@npm:6.4.15" dependencies: "@types/node": "*" - checksum: 5f61f01dd736b17f431d1e8b320322f86460604b45df947fc4bc8999d7c7719405e349f7abba86e4fb100a464a30b52615d00dac03d9cb37562ff04487ebd310 + checksum: f6f9a2f8a669703ecc3ca6359c12345b16f6b2e5691b93c406b9af7de639c02092ec00133526e6fecd8c60d884890a7cd0f967d8e64bedab46d5c3d8be0882d7 languageName: node linkType: hard @@ -4271,16 +4405,16 @@ __metadata: linkType: hard "@types/prop-types@npm:*": - version: 15.7.11 - resolution: "@types/prop-types@npm:15.7.11" - checksum: 7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 + version: 15.7.12 + resolution: "@types/prop-types@npm:15.7.12" + checksum: ac16cc3d0a84431ffa5cfdf89579ad1e2269549f32ce0c769321fdd078f84db4fbe1b461ed5a1a496caf09e637c0e367d600c541435716a55b1d9713f5035dfe languageName: node linkType: hard "@types/qs@npm:*": - version: 6.9.11 - resolution: "@types/qs@npm:6.9.11" - checksum: 620ca1628bf3da65662c54ed6ebb120b18a3da477d0bfcc872b696685a9bb1893c3c92b53a1190a8f54d52eaddb6af8b2157755699ac83164604329935e8a7f2 + version: 6.9.15 + resolution: "@types/qs@npm:6.9.15" + checksum: 97d8208c2b82013b618e7a9fc14df6bd40a73e1385ac479b6896bafc7949a46201c15f42afd06e86a05e914f146f495f606b6fb65610cc60cf2e0ff743ec38a2 languageName: node linkType: hard @@ -4292,22 +4426,21 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0": - version: 18.2.18 - resolution: "@types/react-dom@npm:18.2.18" + version: 18.3.0 + resolution: "@types/react-dom@npm:18.3.0" dependencies: "@types/react": "*" - checksum: 8e3da404c980e2b2a76da3852f812ea6d8b9d0e7f5923fbaf3bfbbbfa1d59116ff91c129de8f68e9b7668a67ae34484fe9df74d5a7518cf8591ec07a0c4dad57 + checksum: a0cd9b1b815a6abd2a367a9eabdd8df8dd8f13f95897b2f9e1359ea3ac6619f957c1432ece004af7d95e2a7caddbba19faa045f831f32d6263483fc5404a7596 languageName: node linkType: hard "@types/react@npm:*, @types/react@npm:^18.2.23": - version: 18.2.46 - resolution: "@types/react@npm:18.2.46" + version: 18.3.3 + resolution: "@types/react@npm:18.3.3" dependencies: "@types/prop-types": "*" - "@types/scheduler": "*" csstype: ^3.0.2 - checksum: cb0e4dc7f41988a059e1246a19ec377101f5b16097ec4bf7000ef3c431ec0c8c873f40e95075821f908db1f4e3352775f0f18cea53dcad14dce67c0f5110f2bd + checksum: c63d6a78163244e2022b01ef79b0baec4fe4da3475dc4a90bb8accefad35ef0c43560fd0312e5974f92a0f1108aa4d669ac72d73d66396aa060ea03b5d2e3873 languageName: node linkType: hard @@ -4320,17 +4453,10 @@ __metadata: languageName: node linkType: hard -"@types/scheduler@npm:*": - version: 0.16.8 - resolution: "@types/scheduler@npm:0.16.8" - checksum: 6c091b096daa490093bf30dd7947cd28e5b2cd612ec93448432b33f724b162587fed9309a0acc104d97b69b1d49a0f3fc755a62282054d62975d53d7fd13472d - languageName: node - linkType: hard - -"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 +"@types/semver@npm:^7.3.12": + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -4345,13 +4471,13 @@ __metadata: linkType: hard "@types/serve-static@npm:*": - version: 1.15.5 - resolution: "@types/serve-static@npm:1.15.5" + version: 1.15.7 + resolution: "@types/serve-static@npm:1.15.7" dependencies: "@types/http-errors": "*" - "@types/mime": "*" "@types/node": "*" - checksum: 0ff4b3703cf20ba89c9f9e345bc38417860a88e85863c8d6fe274a543220ab7f5f647d307c60a71bb57dc9559f0890a661e8dc771a6ec5ef195d91c8afc4a893 + "@types/send": "*" + checksum: bbbf00dbd84719da2250a462270dc68964006e8d62f41fe3741abd94504ba3688f420a49afb2b7478921a1544d3793183ffa097c5724167da777f4e0c7f1a7d6 languageName: node linkType: hard @@ -4370,13 +4496,13 @@ __metadata: linkType: hard "@types/superagent@npm:*": - version: 8.1.1 - resolution: "@types/superagent@npm:8.1.1" + version: 8.1.7 + resolution: "@types/superagent@npm:8.1.7" dependencies: "@types/cookiejar": ^2.1.5 "@types/methods": ^1.1.4 "@types/node": "*" - checksum: 02b987833cf0d85da9b137fd296fe8ad25a470d60f7e9d81a6ed3f8f8a5d6bace8780816bd35885e2928f467e819a4aa509879a7da0f28018ab1453845eb91e2 + checksum: 8f80c72bd1cc9a9295a2e1e8a7a8de9bef09348db63f33cc4f61e457917662064ab86ce013f28249c34d7239d9a4415c1a597dc70d4391b2ad83b338a63a3b73 languageName: node linkType: hard @@ -4403,6 +4529,22 @@ __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.5 + resolution: "@types/whatwg-url@npm:11.0.5" + dependencies: + "@types/webidl-conversions": "*" + checksum: 23a0c45aff51817807b473a6adb181d6e3bb0d27dde54e84883d5d5bc93358e95204d2188e7ff7fdc2cdaf157e97e1188ef0a22ec79228da300fc30d4a05b56a + languageName: node + linkType: hard + "@types/yauzl@npm:^2.9.1": version: 2.10.3 resolution: "@types/yauzl@npm:2.10.3" @@ -4436,46 +4578,80 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^6.7.2": - version: 6.17.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.17.0" +"@typescript-eslint/eslint-plugin@npm:^7.9.0": + version: 7.13.1 + resolution: "@typescript-eslint/eslint-plugin@npm:7.13.1" dependencies: - "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.17.0 - "@typescript-eslint/type-utils": 6.17.0 - "@typescript-eslint/utils": 6.17.0 - "@typescript-eslint/visitor-keys": 6.17.0 - debug: ^4.3.4 + "@eslint-community/regexpp": ^4.10.0 + "@typescript-eslint/scope-manager": 7.13.1 + "@typescript-eslint/type-utils": 7.13.1 + "@typescript-eslint/utils": 7.13.1 + "@typescript-eslint/visitor-keys": 7.13.1 graphemer: ^1.4.0 - ignore: ^5.2.4 + ignore: ^5.3.1 natural-compare: ^1.4.0 - semver: ^7.5.4 - ts-api-utils: ^1.0.1 + ts-api-utils: ^1.3.0 peerDependencies: - "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 + "@typescript-eslint/parser": ^7.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 169646a705fdd1bc2a0d78678dbf3557ff3e534e9d4a11f7b5bba1d9f5cbec821f8c16b260413203efc8d6e0c0a3d7f9332bb1476e3dac80e60aa16eb9a0ad11 + checksum: c79a01cac62c7588c7c968121d39bc5821172e007ab641e0d8d79c176451a3a8b134782df7ef7af0b7d85a8026245d9866ac049596f009f9b19064e0b07ec8d5 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0, @typescript-eslint/parser@npm:^6.7.2": - version: 6.17.0 - resolution: "@typescript-eslint/parser@npm:6.17.0" +"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0": + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: - "@typescript-eslint/scope-manager": 6.17.0 - "@typescript-eslint/types": 6.17.0 - "@typescript-eslint/typescript-estree": 6.17.0 - "@typescript-eslint/visitor-keys": 6.17.0 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: c48864aebf364332540f520d84630a6bb3e2ddc84492d75c14a453964b669a37f1fd43b60469e3683e618e8e8d3d7747baffe92e408599d5df6869cae86ac9e1 + checksum: 162fe3a867eeeffda7328bce32dae45b52283c68c8cb23258fb9f44971f761991af61f71b8c9fe1aa389e93dfe6386f8509c1273d870736c507d76dd40647b68 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/parser@npm:7.2.0" + dependencies: + "@typescript-eslint/scope-manager": 7.2.0 + "@typescript-eslint/types": 7.2.0 + "@typescript-eslint/typescript-estree": 7.2.0 + "@typescript-eslint/visitor-keys": 7.2.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 21deb2e7ad1fc730f637af08f5c549f30ef5b50f424639f57f5bc01274e648db47c696bb994bb24e87424b593d4084e306447c9431a0c0e4807952996db306f4 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^7.9.0": + version: 7.13.1 + resolution: "@typescript-eslint/parser@npm:7.13.1" + dependencies: + "@typescript-eslint/scope-manager": 7.13.1 + "@typescript-eslint/types": 7.13.1 + "@typescript-eslint/typescript-estree": 7.13.1 + "@typescript-eslint/visitor-keys": 7.13.1 + debug: ^4.3.4 + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: a8f39b34f61397c8e34b6716b6e25397d8f770541c3ef67b704850af9b7ce05ee86d5169ef0e983689bf7b063fa47eca5fedee20e08d0567aabbc94a64881543 languageName: node linkType: hard @@ -4489,13 +4665,33 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/scope-manager@npm:6.17.0" +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:7.13.1": + version: 7.13.1 + resolution: "@typescript-eslint/scope-manager@npm:7.13.1" + dependencies: + "@typescript-eslint/types": 7.13.1 + "@typescript-eslint/visitor-keys": 7.13.1 + checksum: 1301cee01efdbd29ed09292e52e6a3fc3a7b6c8713a16d52a385003d99589883f47f4aa6270f22004c2c442b3ee6978883b065be5fb6a41843b6af84d1f32e7c + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/scope-manager@npm:7.2.0" dependencies: - "@typescript-eslint/types": 6.17.0 - "@typescript-eslint/visitor-keys": 6.17.0 - checksum: 6eabac1e52cd25714ab176c7bbf9919d065febf4580620eb067ab1b41607f5e592857bd831a2ab41daa873af4011217dbcae55ed248855e381127f1cabcd2d2c + "@typescript-eslint/types": 7.2.0 + "@typescript-eslint/visitor-keys": 7.2.0 + checksum: b4ef8e35a56f590fa56cf769e111907828abb4793f482bf57e3fc8c987294ec119acb96359aa4b0150eea7416816e0b2d8635dccd1e4a5c2b02678b0f74def94 languageName: node linkType: hard @@ -4516,20 +4712,20 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/type-utils@npm:6.17.0" +"@typescript-eslint/type-utils@npm:7.13.1": + version: 7.13.1 + resolution: "@typescript-eslint/type-utils@npm:7.13.1" dependencies: - "@typescript-eslint/typescript-estree": 6.17.0 - "@typescript-eslint/utils": 6.17.0 + "@typescript-eslint/typescript-estree": 7.13.1 + "@typescript-eslint/utils": 7.13.1 debug: ^4.3.4 - ts-api-utils: ^1.0.1 + ts-api-utils: ^1.3.0 peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: bb6f824c1c7f8d25a21b7218a5bcb74e58c38121f85418eb1639f2931c6149285c2ede96dd677a3e7dc64886cc7640d74be6001d970c3ac9c9a4d889315c5d15 + checksum: 6f1834fae3cc58ce8abfb243fc7d865ad07d0d4d0864ec970b8e97bb6aceb8daa2fa5903d8b44ceedffdbf44092e38634942b3b20d66041aec4c5df42433d293 languageName: node linkType: hard @@ -4540,10 +4736,24 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/types@npm:6.17.0" - checksum: a199516230b505f85de1b99cdf22c526cbae7604fa2dd0dd24e8bba5de45aeaee231263e7e59843af7b226cb91c4ba5447d06517a1a73b511a94c6b483af0d5b +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:7.13.1": + version: 7.13.1 + resolution: "@typescript-eslint/types@npm:7.13.1" + checksum: 0817278c84cde070fed56b55bda538e295a2193cc11d120d7d32fd6030614e209a55093607a25c3071e44ddda7a3e9495ed0b7267a8812f65263db7a230404a1 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/types@npm:7.2.0" + checksum: 237acd24aa55b762ee98904e4f422ba86579325200dcd058b3cbfe70775926e7f00ee0295788d81eb728f3a6326fe4401c648aee9eb1480d9030a441c17520e8 languageName: node linkType: hard @@ -4565,12 +4775,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.17.0" +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" dependencies: - "@typescript-eslint/types": 6.17.0 - "@typescript-eslint/visitor-keys": 6.17.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -4580,19 +4790,57 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 4bf7811ddae66361cad55f7a6fcf9975eb77456ceb2eca5d7a6228387737845bdfe1b9eef4c76d5d6b7c7d6029a8f62bc67b509c0724cd37395ae16eb07dd7ab + checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21 languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/utils@npm:5.62.0" +"@typescript-eslint/typescript-estree@npm:7.13.1": + version: 7.13.1 + resolution: "@typescript-eslint/typescript-estree@npm:7.13.1" dependencies: - "@eslint-community/eslint-utils": ^4.2.0 - "@types/json-schema": ^7.0.9 - "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/types": 7.13.1 + "@typescript-eslint/visitor-keys": 7.13.1 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: ^9.0.4 + semver: ^7.6.0 + ts-api-utils: ^1.3.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: b629b5a58bd9e966cf5071aef28393c503441577b4e23d975db9a6c01e4239ac249bbed2933b02b396befaf9e9da504ed310eabbfce77a8dfb199f237294de05 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.2.0" + dependencies: + "@typescript-eslint/types": 7.2.0 + "@typescript-eslint/visitor-keys": 7.2.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: 9.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: fe882195cad45bb67e7e127efa9c31977348d0ca923ef26bb9fbd03a2ab64e6772e6e60954ba07a437684fae8e35897d71f0e6a1ef8fbf3f0025cd314960cd9d + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@types/json-schema": ^7.0.9 + "@types/semver": ^7.3.12 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 "@typescript-eslint/typescript-estree": 5.62.0 eslint-scope: ^5.1.1 semver: ^7.3.7 @@ -4602,20 +4850,17 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/utils@npm:6.17.0" +"@typescript-eslint/utils@npm:7.13.1": + version: 7.13.1 + resolution: "@typescript-eslint/utils@npm:7.13.1" dependencies: "@eslint-community/eslint-utils": ^4.4.0 - "@types/json-schema": ^7.0.12 - "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.17.0 - "@typescript-eslint/types": 6.17.0 - "@typescript-eslint/typescript-estree": 6.17.0 - semver: ^7.5.4 + "@typescript-eslint/scope-manager": 7.13.1 + "@typescript-eslint/types": 7.13.1 + "@typescript-eslint/typescript-estree": 7.13.1 peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - checksum: 2eea8fd3763b2ab9d86503c68b4d61df81071fd38851b8ba920d53b055c352d13e192a3d15ca853f11aee818c61e8af65946e963aa0e9b18d19e3254881bded0 + eslint: ^8.56.0 + checksum: 83c6af85edb45c81ff3a9d790299f0ea2403033bcb945a5bef726623ca74955979f99e887445b3fe6ba8fde1762d32ff2baa64c0558b56ca84109d4a74e57e26 languageName: node linkType: hard @@ -4629,13 +4874,33 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.17.0" +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + eslint-visitor-keys: ^3.4.1 + checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:7.13.1": + version: 7.13.1 + resolution: "@typescript-eslint/visitor-keys@npm:7.13.1" + dependencies: + "@typescript-eslint/types": 7.13.1 + eslint-visitor-keys: ^3.4.3 + checksum: cfa307e93cca8b2f628fe6b9146a8ea9733fb063a703bdb26f2b4a5c8f52d8e300ec3632c93c12d9f251b595c1b6aab62f9cc9ceac8cda4c618dd7bd6f583b2e + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.2.0" dependencies: - "@typescript-eslint/types": 6.17.0 + "@typescript-eslint/types": 7.2.0 eslint-visitor-keys: ^3.4.1 - checksum: e98755087bd067388d9a9182375e53f590183ca656d02b3d05d9718bab2ac571832fd16691060c7c979fd941e9d4b7923d8975632923697de0691f50fc97c8ac + checksum: d9b11b52737450f213cea5c6e07e4672684da48325905c096ee09302b6b261c0bb226e1e350011bdf127c0cbbdd9e6474c905befdfa0a2118fc89ece16770f2b languageName: node linkType: hard @@ -4646,57 +4911,57 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:1.4.0": - version: 1.4.0 - resolution: "@vitest/expect@npm:1.4.0" +"@vitest/expect@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/expect@npm:1.6.0" dependencies: - "@vitest/spy": 1.4.0 - "@vitest/utils": 1.4.0 + "@vitest/spy": 1.6.0 + "@vitest/utils": 1.6.0 chai: ^4.3.10 - checksum: aca8b0b592bc020febb08767a230a2f4118453904972df06b2a34c76a669e8eb260ddfd8b0cdc152e93dbf21e0d7ae98bdf09fa80477b21145ac21c01fc5a0d3 + checksum: f3a9959ea387622297efed9e3689fd405044a813df5d5923302eaaea831e250d8d6a0ccd44fb387a95c19963242695ed803afc7c46ae06c48a8e06f194951984 languageName: node linkType: hard -"@vitest/runner@npm:1.4.0": - version: 1.4.0 - resolution: "@vitest/runner@npm:1.4.0" +"@vitest/runner@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/runner@npm:1.6.0" dependencies: - "@vitest/utils": 1.4.0 + "@vitest/utils": 1.6.0 p-limit: ^5.0.0 pathe: ^1.1.1 - checksum: 41a847d1ba916c64e482a69342222a40b81014ad06da7ccb7d8cd4119c5718564c22b00367574803642e6ca6ab5678509073b5c460bedc2b385d4e990351012f + checksum: 2dcd953477d5effc051376e35a7f2c2b28abbe07c54e61157c9a6d6f01c880e079592c959397b3a55471423256ab91709c150881a33632558b81b1e251a0bf9c languageName: node linkType: hard -"@vitest/snapshot@npm:1.4.0": - version: 1.4.0 - resolution: "@vitest/snapshot@npm:1.4.0" +"@vitest/snapshot@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/snapshot@npm:1.6.0" dependencies: magic-string: ^0.30.5 pathe: ^1.1.1 pretty-format: ^29.7.0 - checksum: fe495661d682534b41f3ac373c017ac84c04263087a715307715bb41a69c307d6f237b18cc8195bc22d82bf38a1a1a773b0c99715d5de5f40c6169e916b8f4a4 + checksum: c4249fbf3ce310de86a19529a0a5c10b1bde4d8d8a678029c632335969b86cbdbf51cedc20d5e9c9328afee834d13cec1b8de5d0fd58139bf8e2dd8dcd0797f4 languageName: node linkType: hard -"@vitest/spy@npm:1.4.0": - version: 1.4.0 - resolution: "@vitest/spy@npm:1.4.0" +"@vitest/spy@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/spy@npm:1.6.0" dependencies: tinyspy: ^2.2.0 - checksum: 3b1c422760e5840e9e4aa804de7619f3d14e0b364b29f8f030df528206b84c5706792c5d680ac668077d5663f8648a17a783df11cd90ddf2a11000359f1a6286 + checksum: 0201975232255e1197f70fc6b23a1ff5e606138a5b96598fff06077d5b747705391013ee98f951affcfd8f54322e4ae1416200393248bb6a9c794f4ef663a066 languageName: node linkType: hard -"@vitest/utils@npm:1.4.0": - version: 1.4.0 - resolution: "@vitest/utils@npm:1.4.0" +"@vitest/utils@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/utils@npm:1.6.0" dependencies: diff-sequences: ^29.6.3 estree-walker: ^3.0.3 loupe: ^2.3.7 pretty-format: ^29.7.0 - checksum: 5b54e36e5ad236da1da548d31e3b080d1798179f787cfb9ac512d03e59401f8baaa96fec15b6de6b969ee0e057660289109a69a39bd988e89aa72625b5f78484 + checksum: a4749533a48e7e4bbc8eafee0fee0e9a0d4eaa4910fbdb490d34e16f8ebcce59a2b38529b9e6b4578e3b4510ea67b29384c93165712b0a19f2e71946922d2c56 languageName: node linkType: hard @@ -4792,18 +5057,20 @@ __metadata: linkType: hard "acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.3.2": - version: 8.3.2 - resolution: "acorn-walk@npm:8.3.2" - checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + version: 8.3.3 + resolution: "acorn-walk@npm:8.3.3" + dependencies: + acorn: ^8.11.0 + checksum: 0f09d351fc30b69b2b9982bf33dc30f3d35a34e030e5f1ed3c49fc4e3814a192bf3101e4c30912a0595410f5e91bb70ddba011ea73398b3ecbfe41c7334c6dd0 languageName: node linkType: hard -"acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.11.0, acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.9.0": + version: 8.12.0 + resolution: "acorn@npm:8.12.0" bin: acorn: bin/acorn - checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c + checksum: ae142de8739ef15a5d936c550c1d267fc4dedcdbe62ad1aa2c0009afed1de84dd0a584684a5d200bb55d8db14f3e09a95c6e92a5303973c04b9a7413c36d1df0 languageName: node linkType: hard @@ -4823,12 +5090,12 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" dependencies: debug: ^4.3.4 - checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 languageName: node linkType: hard @@ -4904,6 +5171,20 @@ __metadata: languageName: node linkType: hard +"ajv-formats@npm:^3.0.1": + version: 3.0.1 + resolution: "ajv-formats@npm:3.0.1" + dependencies: + ajv: ^8.0.0 + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: f4e1fe232d67fcafc02eafe373a7a9962351e0439dd0736647ca75c93c3da23b430b6502c255ab4315410ae330d4f3013ac9fe226c40b2524ca93a58e786d086 + languageName: node + linkType: hard + "ajv-keywords@npm:^3.5.2": version: 3.5.2 resolution: "ajv-keywords@npm:3.5.2" @@ -4926,14 +5207,14 @@ __metadata: linkType: hard "ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0": - version: 8.12.0 - resolution: "ajv@npm:8.12.0" + version: 8.16.0 + resolution: "ajv@npm:8.16.0" dependencies: - fast-deep-equal: ^3.1.1 + fast-deep-equal: ^3.1.3 json-schema-traverse: ^1.0.0 require-from-string: ^2.0.2 - uri-js: ^4.2.2 - checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 + uri-js: ^4.4.1 + checksum: bdf3d4c9f1d11e220850051ef4cd89346e951cfb933d6d41be36d45053c1092af1523ee6c62525cce567355caf0a4f4c19a08a93851649c1fa32b4a39b7c4858 languageName: node linkType: hard @@ -4963,11 +5244,9 @@ __metadata: linkType: hard "ansi-escapes@npm:^6.2.0": - version: 6.2.0 - resolution: "ansi-escapes@npm:6.2.0" - dependencies: - type-fest: ^3.0.0 - checksum: f0bc667d5f1ededc3ea89b73c34f0cba95473525b07e1290ddfd3fc868c94614e95f3549f5c4fd0c05424af7d3fd298101fb3d9a52a597d3782508b340783bd7 + version: 6.2.1 + resolution: "ansi-escapes@npm:6.2.1" + checksum: 4bdbabe0782a1d4007157798f8acab745d1d5e440c872e6792880d08025e0baababa6b85b36846e955fde7d1e4bf572cdb1fddf109de196e9388d7a1c55ce30d languageName: node linkType: hard @@ -5055,7 +5334,7 @@ __metadata: languageName: node linkType: hard -"archy@npm:^1.0.0, archy@npm:~1.0.0": +"archy@npm:~1.0.0": version: 1.0.0 resolution: "archy@npm:1.0.0" checksum: 504ae7af655130bab9f471343cfdb054feaec7d8e300e13348bc9fe9e660f83d422e473069584f73233c701ae37d1c8452ff2522f2a20c38849e0f406f1732ac @@ -5073,12 +5352,9 @@ __metadata: linkType: hard "are-we-there-yet@npm:^4.0.0": - version: 4.0.1 - resolution: "are-we-there-yet@npm:4.0.1" - dependencies: - delegates: ^1.0.0 - readable-stream: ^4.1.0 - checksum: 16871ee259e138bfab60800ae5b53406fb1b72b5d356f98b13c1b222bb2a13d9bc4292d79f4521fb0eca10874eb3838ae0d9f721f3bb34ddd37ee8f949831800 + version: 4.0.2 + resolution: "are-we-there-yet@npm:4.0.2" + checksum: 29d562d3aad6428aa4d732f78b058f1025fda00305bb307b4cd6ee26a43e5b4c90c113e97e01fa43bfe04556a800ba7e5c947907891ae99bfb8a5ae2488078d0 languageName: node linkType: hard @@ -5104,11 +5380,11 @@ __metadata: linkType: hard "aria-hidden@npm:^1.2.3": - version: 1.2.3 - resolution: "aria-hidden@npm:1.2.3" + version: 1.2.4 + resolution: "aria-hidden@npm:1.2.4" dependencies: tslib: ^2.0.0 - checksum: 7d7d211629eef315e94ed3b064c6823d13617e609d3f9afab1c2ed86399bb8e90405f9bdd358a85506802766f3ecb468af985c67c846045a34b973bcc0289db9 + checksum: 2ac90b70d29c6349d86d90e022cf01f4885f9be193932d943a14127cf28560dd0baf068a6625f084163437a4be0578f513cf7892f4cc63bfe91aa41dce27c6b2 languageName: node linkType: hard @@ -5130,13 +5406,13 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "array-buffer-byte-length@npm:1.0.0" +"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: - call-bind: ^1.0.2 - is-array-buffer: ^3.0.1 - checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 + call-bind: ^1.0.5 + is-array-buffer: ^3.0.4 + checksum: 53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e languageName: node linkType: hard @@ -5161,16 +5437,17 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7": - version: 3.1.7 - resolution: "array-includes@npm:3.1.7" +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7, array-includes@npm:^3.1.8": + version: 3.1.8 + resolution: "array-includes@npm:3.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 is-string: ^1.0.7 - checksum: 06f9e4598fac12a919f7c59a3f04f010ea07f0b7f0585465ed12ef528a60e45f374e79d1bddbb34cdd4338357d00023ddbd0ac18b0be36964f5e726e8965d7fc + checksum: eb39ba5530f64e4d8acab39297c11c1c5be2a4ea188ab2b34aba5fb7224d918f77717a9d57a3e2900caaa8440e59431bdaf5c974d5212ef65d97f132e38e2d91 languageName: node linkType: hard @@ -5198,27 +5475,43 @@ __metadata: linkType: hard "array.prototype.find@npm:^2.1.1": - version: 2.2.2 - resolution: "array.prototype.find@npm:2.2.2" + version: 2.2.3 + resolution: "array.prototype.find@npm:2.2.3" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - checksum: 5daa59fe6b55a449379d91070971cd386b4884bcc97957828c6bd821b49c282cc5b20b2b8d737a815f858d037ba126b0adb04a0690ad4923f69674f2ba704643 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 285bd6248777dc8bd8df3242a7500a04cd3b7ea3dfc6d8de73b10aa583322e85cbfa397e1632aec81bf1e0b5335dcc642d7d0aaa4a3a174a4f8dc70bd63833d2 + languageName: node + linkType: hard + +"array.prototype.findlast@npm:^1.2.5": + version: 1.2.5 + resolution: "array.prototype.findlast@npm:1.2.5" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 83ce4ad95bae07f136d316f5a7c3a5b911ac3296c3476abe60225bc4a17938bf37541972fcc37dd5adbc99cbb9c928c70bbbfc1c1ce549d41a415144030bb446 languageName: node linkType: hard "array.prototype.findlastindex@npm:^1.2.3": - version: 1.2.3 - resolution: "array.prototype.findlastindex@npm:1.2.3" + version: 1.2.5 + resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.2.1 - checksum: 31f35d7b370c84db56484618132041a9af401b338f51899c2e78ef7690fbba5909ee7ca3c59a7192085b328cc0c68c6fd1f6d1553db01a689a589ae510f3966e + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-shim-unscopables: ^1.0.2 + checksum: 2c81cff2a75deb95bf1ed89b6f5f2bfbfb882211e3b7cc59c3d6b87df774cd9d6b36949a8ae39ac476e092c1d4a4905f5ee11a86a456abb10f35f8211ae4e710 languageName: node linkType: hard @@ -5234,7 +5527,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.flatmap@npm:^1.3.1, array.prototype.flatmap@npm:^1.3.2": +"array.prototype.flatmap@npm:^1.3.2": version: 1.3.2 resolution: "array.prototype.flatmap@npm:1.3.2" dependencies: @@ -5246,31 +5539,44 @@ __metadata: languageName: node linkType: hard -"array.prototype.tosorted@npm:^1.1.1": +"array.prototype.toreversed@npm:^1.1.2": version: 1.1.2 - resolution: "array.prototype.tosorted@npm:1.1.2" + resolution: "array.prototype.toreversed@npm:1.1.2" dependencies: call-bind: ^1.0.2 define-properties: ^1.2.0 es-abstract: ^1.22.1 es-shim-unscopables: ^1.0.0 - get-intrinsic: ^1.2.1 - checksum: 3607a7d6b117f0ffa6f4012457b7af0d47d38cf05e01d50e09682fd2fb782a66093a5e5fbbdbad77c8c824794a9d892a51844041641f719ad41e3a974f0764de + checksum: 58598193426282155297bedf950dc8d464624a0d81659822fb73124286688644cb7e0e4927a07f3ab2daaeb6617b647736cc3a5e6ca7ade5bb8e573b284e6240 languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.2": - version: 1.0.2 - resolution: "arraybuffer.prototype.slice@npm:1.0.2" +"array.prototype.tosorted@npm:^1.1.4": + version: 1.1.4 + resolution: "array.prototype.tosorted@npm:1.1.4" dependencies: - array-buffer-byte-length: ^1.0.0 - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - is-array-buffer: ^3.0.2 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.3 + es-errors: ^1.3.0 + es-shim-unscopables: ^1.0.2 + checksum: e4142d6f556bcbb4f393c02e7dbaea9af8f620c040450c2be137c9cbbd1a17f216b9c688c5f2c08fbb038ab83f55993fa6efdd9a05881d84693c7bcb5422127a + languageName: node + linkType: hard + +"arraybuffer.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "arraybuffer.prototype.slice@npm:1.0.3" + dependencies: + array-buffer-byte-length: ^1.0.1 + call-bind: ^1.0.5 + define-properties: ^1.2.1 + es-abstract: ^1.22.3 + es-errors: ^1.2.1 + get-intrinsic: ^1.2.3 + is-array-buffer: ^3.0.4 is-shared-array-buffer: ^1.0.2 - checksum: c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3 + checksum: 352259cba534dcdd969c92ab002efd2ba5025b2e3b9bead3973150edbdf0696c629d7f4b3f061c5931511e8207bdc2306da614703c820b45dabce39e3daf7e3e languageName: node linkType: hard @@ -5332,15 +5638,6 @@ __metadata: languageName: node linkType: hard -"asynciterator.prototype@npm:^1.0.0": - version: 1.0.0 - resolution: "asynciterator.prototype@npm:1.0.0" - dependencies: - has-symbols: ^1.0.3 - checksum: e8ebfd9493ac651cf9b4165e9d64030b3da1d17181bb1963627b59e240cdaf021d9b59d44b827dc1dde4e22387ec04c2d0f8720cf58a1c282e34e40cc12721b3 - languageName: node - linkType: hard - "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -5369,27 +5666,28 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: ^1.0.0 + checksum: 1aa3ffbfe6578276996de660848b6e95669d9a95ad149e3dd0c0cda77db6ee1dbd9d1dd723b65b6d277b882dd0c4b91a654ae9d3cf9e1254b7e93e4908d78fd3 languageName: node linkType: hard -"avvio@npm:^8.2.1": - version: 8.2.1 - resolution: "avvio@npm:8.2.1" +"avvio@npm:^8.3.0": + version: 8.3.2 + resolution: "avvio@npm:8.3.2" dependencies: - archy: ^1.0.0 - debug: ^4.0.0 - fastq: ^1.6.1 - checksum: 4c96922ea123d13b26cb78a071a8989fde62ee8580352b6d2f05b7976ed3d23efa663c12ee1be35501dfe65e12a769a2ea522bcdb7ca35a5ba4d86766467075a + "@fastify/error": ^3.3.0 + fastq: ^1.17.1 + checksum: 137a4a4962e6559665f0d3fef7a06d1932edf284043dc7c2f947e2acf07f2e350fe48784a5d081069e56d299d4a1020cc8679930a53744e356862996d0b23e3f languageName: node linkType: hard "aws-sdk@npm:^2.1466.0": - version: 2.1528.0 - resolution: "aws-sdk@npm:2.1528.0" + version: 2.1644.0 + resolution: "aws-sdk@npm:2.1644.0" dependencies: buffer: 4.9.2 events: 1.1.1 @@ -5400,8 +5698,8 @@ __metadata: url: 0.10.3 util: ^0.12.4 uuid: 8.0.0 - xml2js: 0.5.0 - checksum: 0ac9818b0c212df84b072f570b517cf24a12aeef5fdc2d01cbec3514407bcd40a144a5f3306596e828661885e4d9e34dd398e0f75dfc58792dd08a5d96f08f08 + xml2js: 0.6.2 + checksum: 588042b1c6476d70ae18d5ffa14a1a075d2e869b10c699ad2c5e3034284c94eae1ed3b5bd759b0b900de15504c892575d6284f12e26b13b9d50ae870a35adc65 languageName: node linkType: hard @@ -5413,9 +5711,9 @@ __metadata: linkType: hard "aws4@npm:^1.8.0": - version: 1.12.0 - resolution: "aws4@npm:1.12.0" - checksum: 68f79708ac7c335992730bf638286a3ee0a645cf12575d557860100767c500c08b30e24726b9f03265d74116417f628af78509e1333575e9f8d52a80edfe8cbc + version: 1.13.0 + resolution: "aws4@npm:1.13.0" + checksum: 71594a17a5f7b1a9151ef515500c18f1029caa51e2cb65c1b5b324d9bd8dac89896a9e296825d4e6befdcd612d7fc3b0d8042c667555a56df3ee1ab15d4d9b35 languageName: node linkType: hard @@ -5427,26 +5725,26 @@ __metadata: linkType: hard "axios-cache-interceptor@npm:^1.3.2": - version: 1.4.1 - resolution: "axios-cache-interceptor@npm:1.4.1" + version: 1.5.3 + resolution: "axios-cache-interceptor@npm:1.5.3" dependencies: - cache-parser: 1.2.4 + cache-parser: 1.2.5 fast-defer: 1.1.8 - object-code: 1.3.2 + object-code: 1.3.3 peerDependencies: axios: ^1 - checksum: e3876da4836d4354d8424d0273469421a4dce4676dcf5000d17917b17c67288f6d330db12970a69fcf0e5d419a3f5fb5dd5e3bc880ef58984ad48c80fc5d7ebf + checksum: 69850a6330528e38de0c1922c5fa6698e404a8283e99dc38141c06501d74fb8a54bbb10bd073e2833eb1060bf93cf4d2f09210cdfe166de6e62347169c412658 languageName: node linkType: hard "axios@npm:^1.5.1": - version: 1.6.3 - resolution: "axios@npm:1.6.3" + version: 1.7.2 + resolution: "axios@npm:1.7.2" dependencies: - follow-redirects: ^1.15.0 + follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: 07ef3bb83fc2dacc1ae2c97f2bbd04ef7701f5655f9037789d79ee78b698ffa50eaa8465c2017d4d3e9ce7d94cb779f730acaab32ce9036d0a4933c1e89df4da + checksum: e457e2b0ab748504621f6fa6609074ac08c824bf0881592209dfa15098ece7e88495300e02cd22ba50b3468fd712fe687e629dcb03d6a3f6a51989727405aedf languageName: node linkType: hard @@ -5492,9 +5790,9 @@ __metadata: linkType: hard "basic-ftp@npm:^5.0.3": - version: 5.0.4 - resolution: "basic-ftp@npm:5.0.4" - checksum: 57725f24debd8c1b36f9bad1bfee39c5d9f5997f32a23e5c957389dcc64373a13b41711e5723b4a3b616a93530b345686119f480c27a115b2fde944c1652ceb1 + version: 5.0.5 + resolution: "basic-ftp@npm:5.0.5" + checksum: bc82d1c1c61cd838eaca96d68ece888bacf07546642fb6b9b8328ed410756f5935f8cf43a42cb44bb343e0565e28e908adc54c298bd2f1a6e0976871fb11fec6 languageName: node linkType: hard @@ -5514,6 +5812,15 @@ __metadata: languageName: node linkType: hard +"bidi-js@npm:^1.0.3": + version: 1.0.3 + resolution: "bidi-js@npm:1.0.3" + dependencies: + require-from-string: ^2.0.2 + checksum: 877c5dcfd69a35fd30fee9e49a03faf205a7a4cd04a38af7648974a659cab7b1cd51fa881d7957c07bd1fc5adf22b90a56da3617bb0885ee69d58ff41117658c + languageName: node + linkType: hard + "big-integer@npm:^1.6.16": version: 1.6.52 resolution: "big-integer@npm:1.6.52" @@ -5529,31 +5836,21 @@ __metadata: linkType: hard "bin-links@npm:^4.0.1": - version: 4.0.3 - resolution: "bin-links@npm:4.0.3" + version: 4.0.4 + resolution: "bin-links@npm:4.0.4" dependencies: cmd-shim: ^6.0.0 npm-normalize-package-bin: ^3.0.0 read-cmd-shim: ^4.0.0 write-file-atomic: ^5.0.0 - checksum: 3b3ee22efc38d608479d51675c8958a841b8b55b8975342ce86f28ac4e0bb3aef46e9dbdde976c6dc1fe1bd2aa00d42e00869ad35b57ee6d868f39f662858911 + checksum: 9fca1fddaa3c1c9f7efd6fd7a6d991e3d8f6aaa9de5d0b9355469c2c594d8d06c9b2e0519bb0304202c14ddbe832d27b6d419d55cea4340e2c26116f9190e5c9 languageName: node linkType: hard "binary-extensions@npm:^2.0.0, binary-extensions@npm:^2.2.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 - languageName: node - linkType: hard - -"bl@npm:^2.2.1": - version: 2.2.1 - resolution: "bl@npm:2.2.1" - dependencies: - readable-stream: ^2.3.5 - safe-buffer: ^5.1.1 - checksum: 4f5d9b258919646a8d02f1731379e53b6f6309e34596ae02afbc3aeb183910bd2d0b70681f889b7c620ca48f65dc1cd0992ee1266c90d6d7c3be60688d141233 + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: bcad01494e8a9283abf18c1b967af65ee79b0c6a9e6fcfafebfe91dbe6e0fc7272bafb73389e198b310516ae04f7ad17d79aacf6cb4c0d5d5202a7e2e52c7d98 languageName: node linkType: hard @@ -5575,13 +5872,6 @@ __metadata: languageName: node linkType: hard -"bluebird@npm:3.5.1": - version: 3.5.1 - resolution: "bluebird@npm:3.5.1" - checksum: 0c4b4b93c119c9631fe8987a69f4d06eee204d4e0979defd9d121ab82861bbf0d546e888b3ccf67d5aefd34bcbf5a898a353b788f00c338b390e7c303ce89cf7 - languageName: node - linkType: hard - "bluebird@npm:^3.7.2": version: 3.7.2 resolution: "bluebird@npm:3.7.2" @@ -5589,12 +5879,12 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.1": - version: 1.20.1 - resolution: "body-parser@npm:1.20.1" +"body-parser@npm:1.20.2": + version: 1.20.2 + resolution: "body-parser@npm:1.20.2" dependencies: bytes: 3.1.2 - content-type: ~1.0.4 + content-type: ~1.0.5 debug: 2.6.9 depd: 2.0.0 destroy: 1.2.0 @@ -5602,10 +5892,10 @@ __metadata: iconv-lite: 0.4.24 on-finished: 2.4.1 qs: 6.11.0 - raw-body: 2.5.1 + raw-body: 2.5.2 type-is: ~1.6.18 unpipe: 1.0.0 - checksum: f1050dbac3bede6a78f0b87947a8d548ce43f91ccc718a50dd774f3c81f2d8b04693e52acf62659fad23101827dd318da1fb1363444ff9a8482b886a3e4a5266 + checksum: 14d37ec638ab5c93f6099ecaed7f28f890d222c650c69306872e00b9efa081ff6c596cd9afb9930656aae4d6c4e1c17537bea12bb73c87a217cb3cfea8896737 languageName: node linkType: hard @@ -5651,12 +5941,12 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.1, braces@npm:^3.0.2, braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.1, braces@npm:^3.0.2, braces@npm:^3.0.3, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 languageName: node linkType: hard @@ -5683,10 +5973,10 @@ __metadata: languageName: node linkType: hard -"bson@npm:^1.1.4": - version: 1.1.6 - resolution: "bson@npm:1.1.6" - checksum: 75762c9b7e0b3156cb0f38c7eb9ffcade53f0b04ac87dece9cba38f6dc570d9af91251de6a8988b294063cfaa21894c60ac9e85c34176accb3674acb092d66a7 +"bson@npm:^6.7.0": + version: 6.7.0 + resolution: "bson@npm:6.7.0" + checksum: f77b7001e2ec603b1058e9f2d99b642be4673e0356adf4fbdc463afd89de434d3be9d81305c1befbcda9bf8616e70a8f7ec0c8ec7a79154ca40ba455b73ea280 languageName: node linkType: hard @@ -5715,7 +6005,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.5.0, buffer@npm:^5.6.0": +"buffer@npm:^5.5.0, buffer@npm:^5.7.1": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -5742,23 +6032,23 @@ __metadata: languageName: node linkType: hard -"builtins@npm:^5.0.0, builtins@npm:^5.0.1": - version: 5.0.1 - resolution: "builtins@npm:5.0.1" +"builtins@npm:^5.0.1": + version: 5.1.0 + resolution: "builtins@npm:5.1.0" dependencies: semver: ^7.0.0 - checksum: 66d204657fe36522822a95b288943ad11b58f5eaede235b11d8c4edaa28ce4800087d44a2681524c340494aadb120a0068011acabe99d30e8f11a7d826d83515 + checksum: 76327fa85b8e253b26e52f79988148013ea742691b4ab15f7228ebee47dd757832da308c9d4e4fc89763a1773e3f25a9836fff6315df85c7c6c72190436bf11d languageName: node linkType: hard "bundle-require@npm:^4.0.0": - version: 4.0.2 - resolution: "bundle-require@npm:4.0.2" + version: 4.2.1 + resolution: "bundle-require@npm:4.2.1" dependencies: load-tsconfig: ^0.2.3 peerDependencies: esbuild: ">=0.17" - checksum: 13a78ac0aee0f33614c24f2747167c7faebef6c9d1d5453b464fc85fa164a3a3aab657b2b31b7b5d2a088e4958676fef0454328ff7baddd6bfb03a8ff8d8b928 + checksum: dcf97683772bd9b1461bde9ba83d2dc0f13c5d7aeecfc9d6e3678b21eeb859a03ee815db03ed14af9d7b1311f39e99ce0487d6f67f9244381436eecf478c9a2c languageName: node linkType: hard @@ -5851,7 +6141,7 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^17.0.0, cacache@npm:^17.0.4, cacache@npm:^17.1.3": +"cacache@npm:^17.0.0, cacache@npm:^17.0.4, cacache@npm:^17.1.4": version: 17.1.4 resolution: "cacache@npm:17.1.4" dependencies: @@ -5872,8 +6162,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.1 - resolution: "cacache@npm:18.0.1" + version: 18.0.3 + resolution: "cacache@npm:18.0.3" dependencies: "@npmcli/fs": ^3.1.0 fs-minipass: ^3.0.0 @@ -5887,14 +6177,14 @@ __metadata: ssri: ^10.0.0 tar: ^6.1.11 unique-filename: ^3.0.0 - checksum: 5a0b3b2ea451a0379814dc1d3c81af48c7c6db15cd8f7d72e028501ae0036a599a99bbac9687bfec307afb2760808d1c7708e9477c8c70d2b166e7d80b162a23 + checksum: b717fd9b36e9c3279bfde4545c3a8f6d5a539b084ee26a9504d48f83694beb724057d26e090b97540f9cc62bea18b9f6cf671c50e18fb7dac60eda9db691714f languageName: node linkType: hard -"cache-parser@npm:1.2.4": - version: 1.2.4 - resolution: "cache-parser@npm:1.2.4" - checksum: de9fc4ab7af318109f1e53474e674d43997bc7b8676157e4f28e7dc60fda2f434ee138aa9d9abb9f849c55e73202ee74865afaa4e00298de70c4326510680c19 +"cache-parser@npm:1.2.5": + version: 1.2.5 + resolution: "cache-parser@npm:1.2.5" + checksum: ac6a15462e474a84b8830795aa3d34b63f09a2ef8ec1a3831e7941a7a7aece964df881da275dfc1e8e1874a3a56efd944de0a6bcd371e409d545ca49fd04cdd7 languageName: node linkType: hard @@ -5949,14 +6239,16 @@ __metadata: 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" +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 function-bind: ^1.1.2 - get-intrinsic: ^1.2.1 - set-function-length: ^1.1.1 - checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + get-intrinsic: ^1.2.4 + set-function-length: ^1.2.1 + checksum: 295c0c62b90dd6522e6db3b0ab1ce26bdf9e7404215bda13cfee25b626b5ff1a7761324d58d38b1ef1607fc65aca2d06e44d2e18d0dfc6c14b465b00d8660029 languageName: node linkType: hard @@ -6014,10 +6306,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001406": - version: 1.0.30001572 - resolution: "caniuse-lite@npm:1.0.30001572" - checksum: 7d017a99a38e29ccee4ed3fc0ef1eb90cf082fcd3a7909c5c536c4ba1d55c5b26ecc1e4ad82c1caa6bfadce526764b354608710c9b61a75bdc7ce8ca15c5fcf2 +"caniuse-lite@npm:^1.0.30001579": + version: 1.0.30001636 + resolution: "caniuse-lite@npm:1.0.30001636" + checksum: b0347fd2c8d346680a64d98b061c59cb8fbf149cdd03005a447fae4d21e6286d5bd161b43eefe3221c6624aacb3cda4e838ae83c95ff5313a547f84ca93bcc70 languageName: node linkType: hard @@ -6058,8 +6350,8 @@ __metadata: linkType: hard "chai@npm:^4.3.10": - version: 4.3.10 - resolution: "chai@npm:4.3.10" + version: 4.4.1 + resolution: "chai@npm:4.4.1" dependencies: assertion-error: ^1.1.0 check-error: ^1.0.3 @@ -6068,7 +6360,7 @@ __metadata: loupe: ^2.3.6 pathval: ^1.1.1 type-detect: ^4.0.8 - checksum: 536668c60a0d985a0fbd94418028e388d243a925d7c5e858c7443e334753511614a3b6a124bac9ca077dfc4c37acc367d62f8c294960f440749536dc181dfc6d + checksum: 9ab84f36eb8e0b280c56c6c21ca4da5933132cd8a0c89c384f1497f77953640db0bc151edd47f81748240a9fab57b78f7d925edfeedc8e8fc98016d71f40c36e languageName: node linkType: hard @@ -6184,8 +6476,8 @@ __metadata: linkType: hard "chokidar@npm:^3.0.0, chokidar@npm:^3.5.1": - version: 3.5.3 - resolution: "chokidar@npm:3.5.3" + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" dependencies: anymatch: ~3.1.2 braces: ~3.0.2 @@ -6198,7 +6490,7 @@ __metadata: dependenciesMeta: fsevents: optional: true - checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c + checksum: d2f29f499705dcd4f6f3bbed79a9ce2388cf530460122eed3b9c48efeab7a4e28739c6551fd15bec9245c6b9eeca7a32baa64694d64d9b6faeb74ddb8c4a413d languageName: node linkType: hard @@ -6209,13 +6501,20 @@ __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.2.0": version: 3.9.0 resolution: "ci-info@npm:3.9.0" checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 languageName: node linkType: hard +"ci-info@npm:^4.0.0": + version: 4.0.0 + resolution: "ci-info@npm:4.0.0" + checksum: 122fe41c5eb8d0b5fa0ab6fd674c5ddcf2dc59766528b062a0144ff0d913cfb210ef925ec52110e7c2a7f4e603d5f0e8b91cfe68867e196e9212fa0b94d0a08a + languageName: node + linkType: hard + "cidr-regex@npm:^3.1.1": version: 3.1.1 resolution: "cidr-regex@npm:3.1.1" @@ -6308,7 +6607,7 @@ __metadata: 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.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -6321,6 +6620,19 @@ __metadata: languageName: node linkType: hard +"cli-table3@npm:^0.6.1, cli-table3@npm:^0.6.3, cli-table3@npm:~0.6.1": + version: 0.6.5 + resolution: "cli-table3@npm:0.6.5" + dependencies: + "@colors/colors": 1.5.0 + string-width: ^4.2.0 + dependenciesMeta: + "@colors/colors": + optional: true + checksum: ab7afbf4f8597f1c631f3ee6bb3481d0bfeac8a3b81cffb5a578f145df5c88003b6cfff46046a7acae86596fdd03db382bfa67f20973b6b57425505abc47e42c + languageName: node + linkType: hard + "cli-truncate@npm:^2.1.0": version: 2.1.0 resolution: "cli-truncate@npm:2.1.0" @@ -6355,17 +6667,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" @@ -6401,9 +6702,9 @@ __metadata: linkType: hard "cmd-shim@npm:^6.0.0": - version: 6.0.2 - resolution: "cmd-shim@npm:6.0.2" - checksum: df3a01fc4d72a49b450985b991205e65774b28e7f74a2e4d2a11fd0df8732e3828f9e7b644050def3cd0be026cbd3ee46a1f50ce5f57d0b3fb5afe335bdfacde + version: 6.0.3 + resolution: "cmd-shim@npm:6.0.3" + checksum: bd79ac1505fea77cba0caf271c16210ebfbe50f348a1907f4700740876ab2157e00882b9baa685a9fcf9bc92e08a87e21bd757f45a6938f00290422f80f7d27a languageName: node linkType: hard @@ -6605,6 +6906,13 @@ __metadata: languageName: node linkType: hard +"confbox@npm:^0.1.7": + version: 0.1.7 + resolution: "confbox@npm:0.1.7" + checksum: bde836c26f5154a348b0c0a757f8a0138929e5737e0553be3c4f07a056abca618b861aa63ac3b22d344789b56be99a1382928933e08cd500df00213bf4d8fb43 + languageName: node + linkType: hard + "config-chain@npm:^1.1.11, config-chain@npm:^1.1.13": version: 1.1.13 resolution: "config-chain@npm:1.1.13" @@ -6638,7 +6946,7 @@ __metadata: languageName: node linkType: hard -"content-type@npm:~1.0.4": +"content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 @@ -6753,7 +7061,14 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0, cookie@npm:^0.5.0": +"cookie@npm:0.6.0, cookie@npm:^0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: f56a7d32a07db5458e79c726b77e3c2eff655c36792f2b6c58d351fb5f61531e5b1ab7f46987150136e366c65213cbe31729e02a3eaed630c3bf7334635fb410 + languageName: node + linkType: hard + +"cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180 @@ -6940,6 +7255,16 @@ __metadata: languageName: node linkType: hard +"css-tree@npm:^2.3.1": + version: 2.3.1 + resolution: "css-tree@npm:2.3.1" + dependencies: + mdn-data: 2.0.30 + source-map-js: ^1.0.1 + checksum: 493cc24b5c22b05ee5314b8a0d72d8a5869491c1458017ae5ed75aeb6c3596637dbe1b11dac2548974624adec9f7a1f3a6cf40593dc1f9185eb0e8279543fbc0 + languageName: node + linkType: hard + "css-what@npm:^6.1.0": version: 6.1.0 resolution: "css-what@npm:6.1.0" @@ -6963,12 +7288,12 @@ __metadata: languageName: node linkType: hard -"cssstyle@npm:^3.0.0": - version: 3.0.0 - resolution: "cssstyle@npm:3.0.0" +"cssstyle@npm:^4.0.1": + version: 4.0.1 + resolution: "cssstyle@npm:4.0.1" dependencies: rrweb-cssom: ^0.6.0 - checksum: 31f694dfed9998ed93570fe539610837b878193dd8487c33cb12db8004333c53c2a3904166288bbec68388c72fb01014d46d3243ddfb02fe845989d852c06f27 + checksum: 4b2fdd81c565b1f8f24a792f85d3a19269a2f201e731c3fe3531d7fc78b4bc6b31906ed17aba7edba7b1c8b7672574fc6c09fe925556da3a9a9458dbf8c4fa22 languageName: node linkType: hard @@ -6980,9 +7305,9 @@ __metadata: linkType: hard "csv-parse@npm:^5.5.0": - version: 5.5.3 - resolution: "csv-parse@npm:5.5.3" - checksum: 38399bc4c61b721bc2f52a6262d6000b4e5f391e45b071f6eb087b293a02f867020f7da36adf6f56eb9fb45bd28c82cd223afd35846551fb5ad31bf3d0602961 + version: 5.5.6 + resolution: "csv-parse@npm:5.5.6" + checksum: ee06f97f674487dc1d001b360de8ea510a41b9d971abf43bcf9c3be22c83a3634df0d3ebfbe52fd49d145077066be7ff9f25de3fc6b71aefb973099b04147a25 languageName: node linkType: hard @@ -7017,8 +7342,8 @@ __metadata: linkType: hard "cypress@npm:^13.6.4": - version: 13.6.4 - resolution: "cypress@npm:13.6.4" + version: 13.12.0 + resolution: "cypress@npm:13.12.0" dependencies: "@cypress/request": ^3.0.0 "@cypress/xvfb": ^1.2.4 @@ -7027,7 +7352,7 @@ __metadata: arch: ^2.2.0 blob-util: ^2.0.2 bluebird: ^3.7.2 - buffer: ^5.6.0 + buffer: ^5.7.1 cachedir: ^2.3.0 chalk: ^4.1.0 check-more-types: ^2.24.0 @@ -7045,7 +7370,7 @@ __metadata: figures: ^3.2.0 fs-extra: ^9.1.0 getos: ^3.2.1 - is-ci: ^3.0.0 + is-ci: ^3.0.1 is-installed-globally: ~0.4.0 lazy-ass: ^1.6.0 listr2: ^3.8.3 @@ -7064,17 +7389,17 @@ __metadata: yauzl: ^2.10.0 bin: cypress: bin/cypress - checksum: 39daef291ccd18d7d724d7f8c1f5a2ed2b3d24c5c1eab1e00642c5db232fcc4dbd3fd30db3a2dce4e8b737d510355d135eb43034d800198d2867ecde4cdd696a + checksum: b60d6c6bddd129417a87b96add07a71aa5fd04d3d9ee52f9e5e6fdbe1cf117bba0769d4cce4e6fe6536219eaceb53b3dc4a19fc161d6b0f5a2401afde348f703 languageName: node linkType: hard -"d@npm:1, d@npm:^1.0.1": - version: 1.0.1 - resolution: "d@npm:1.0.1" +"d@npm:1, d@npm:^1.0.1, d@npm:^1.0.2": + version: 1.0.2 + resolution: "d@npm:1.0.2" dependencies: - es5-ext: ^0.10.50 - type: ^1.0.1 - checksum: 49ca0639c7b822db670de93d4fbce44b4aa072cd848c76292c9978a8cd0fff1028763020ff4b0f147bd77bfe29b4c7f82e0f71ade76b2a06100543cdfd948d19 + es5-ext: ^0.10.64 + type: ^2.7.2 + checksum: 775db1e8ced6707cddf64a5840522fcf5475d38ef49a5d615be0ac47f86ef64d15f5a73de1522b09327cc466d4dc35ea83dbfeed456f7a0fdcab138deb800355 languageName: node linkType: hard @@ -7111,6 +7436,39 @@ __metadata: languageName: node linkType: hard +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: ce24348f3c6231223b216da92e7e6a57a12b4af81a23f27eff8feabdf06acfb16c00639c8b705ca4d167f761cfc756e27e5f065d0a1f840c10b907fdaf8b988c + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: dbb3200edcb7c1ef0d68979834f81d64fd8cab2f7691b3a4c6b97e67f22182f3ec2c8602efd7b76997b55af6ff8bce485829c1feda4fa2165a6b71fb7baa4269 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: 7f0bf8720b7414ca719eedf1846aeec392f2054d7af707c5dc9a753cc77eb8625f067fa901e0b5127e831f9da9056138d894b9c2be79c27a21f6db5824f009c2 + languageName: node + linkType: hard + "date-fns@npm:^2.15.0, date-fns@npm:^2.28.0, date-fns@npm:^2.30.0": version: 2.30.0 resolution: "date-fns@npm:2.30.0" @@ -7135,9 +7493,9 @@ __metadata: linkType: hard "dayjs@npm:^1.10.4, dayjs@npm:^1.11.10": - version: 1.11.10 - resolution: "dayjs@npm:1.11.10" - checksum: a6b5a3813b8884f5cd557e2e6b7fa569f4c5d0c97aca9558e38534af4f2d60daafd3ff8c2000fed3435cfcec9e805bcebd99f90130c6d1c5ef524084ced588c4 + version: 1.11.11 + resolution: "dayjs@npm:1.11.11" + checksum: 84788275aad8a87fee4f1ce4be08861df29687aae6b7b43dd65350118a37dda56772a3902f802cb2dc651dfed447a5a8df62d88f0fb900dba8333e411190a5d5 languageName: node linkType: hard @@ -7150,16 +7508,19 @@ __metadata: languageName: node linkType: hard -"debug@npm:3.1.0": - version: 3.1.0 - resolution: "debug@npm:3.1.0" +"debug@npm: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.5 + resolution: "debug@npm:4.3.5" dependencies: - ms: 2.0.0 - checksum: 0b52718ab957254a5b3ca07fc34543bc778f358620c206a08452251eb7fc193c3ea3505072acbf4350219c14e2d71ceb7bdaa0d3370aa630b50da790458d08b3 + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 7c002b51e256257f936dda09eb37167df952758c57badf6bf44bdc40b89a4bcb8e5a0a2e4c7b53f97c69e2970dd5272d33a757378a12c8f8e64ea7bf99e8e86e 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.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -7221,11 +7582,11 @@ __metadata: linkType: hard "deep-eql@npm:^4.1.3": - version: 4.1.3 - resolution: "deep-eql@npm:4.1.3" + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" dependencies: type-detect: ^4.0.0 - checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f + checksum: 01c3ca78ff40d79003621b157054871411f94228ceb9b2cab78da913c606631c46e8aa79efc4aa0faf3ace3092acd5221255aab3ef0e8e7b438834f0ca9a16c7 languageName: node linkType: hard @@ -7306,14 +7667,14 @@ __metadata: 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" +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" dependencies: - get-intrinsic: ^1.2.1 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + checksum: 8068ee6cab694d409ac25936eb861eea704b7763f7f342adbdfe337fc27c78d7ae0eff2364b2917b58c508d723c7a074326d068eef2e45c4edcd85cf94d0313b languageName: node linkType: hard @@ -7342,13 +7703,6 @@ __metadata: languageName: node linkType: hard -"denque@npm:^1.4.1": - version: 1.5.1 - resolution: "denque@npm:1.5.1" - checksum: 4375ad19d5cea99f90effa82a8cecdaa10f4eb261fbcd7e47cd753ff2737f037aac8f7f4e031cc77f3966314c491c86a0d3b20c128aeee57f791b4662c45108e - languageName: node - linkType: hard - "depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" @@ -7384,14 +7738,7 @@ __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, detect-node@npm:^2.1.0": +"detect-node@npm:2.1.0, detect-node@npm:^2.0.4, detect-node@npm:^2.1.0": version: 2.1.0 resolution: "detect-node@npm:2.1.0" checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e @@ -7423,9 +7770,9 @@ __metadata: linkType: hard "diff@npm:^5.1.0": - version: 5.1.0 - resolution: "diff@npm:5.1.0" - checksum: c7bf0df7c9bfbe1cf8a678fd1b2137c4fb11be117a67bc18a0e03ae75105e8533dbfb1cda6b46beb3586ef5aed22143ef9d70713977d5fb1f9114e21455fba90 + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 12b63ca9c36c72bafa3effa77121f0581b4015df18bc16bac1f8e263597735649f1a173c26f7eba17fb4162b073fee61788abe49610e6c70a2641fe1895443fd languageName: node linkType: hard @@ -7571,9 +7918,9 @@ __metadata: linkType: hard "dompurify@npm:^3.0.6": - version: 3.0.6 - resolution: "dompurify@npm:3.0.6" - checksum: e5c6cdc5fe972a9d0859d939f1d86320de275be00bbef7bd5591c80b1e538935f6ce236624459a1b0c84ecd7c6a1e248684aa4637512659fccc0ce7c353828a6 + version: 3.1.5 + resolution: "dompurify@npm:3.1.5" + checksum: 18ae2930cba3c260889b99e312c382c344d219bd113bc39fbb665a61987d25849021768f490395e6954aab94448a24b3c3721c160b53550547110c37cebe9feb languageName: node linkType: hard @@ -7598,7 +7945,7 @@ __metadata: languageName: node linkType: hard -"domutils@npm:^3.0.1": +"domutils@npm:^3.0.1, domutils@npm:^3.1.0": version: 3.1.0 resolution: "domutils@npm:3.1.0" dependencies: @@ -7619,9 +7966,9 @@ __metadata: linkType: hard "dotenv@npm:^16.1.4, dotenv@npm:^16.3.1": - version: 16.3.1 - resolution: "dotenv@npm:16.3.1" - checksum: 15d75e7279018f4bafd0ee9706593dd14455ddb71b3bcba9c52574460b7ccaf67d5cf8b2c08a5af1a9da6db36c956a04a1192b101ee102a3e0cf8817bbcf3dfd + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 301a12c3d44fd49888b74eb9ccf9f07a1f5df43f489e7fcb89647a2edcd84c42d6bc349dc8df099cd18f07c35c7b04685c1a4f3e6a6a9e6b30f8d48c15b7f49c languageName: node linkType: hard @@ -7698,7 +8045,7 @@ __metadata: languageName: node linkType: hard -"editorconfig@npm:^1.0.3": +"editorconfig@npm:^1.0.4": version: 1.0.4 resolution: "editorconfig@npm:1.0.4" dependencies: @@ -7720,13 +8067,13 @@ __metadata: linkType: hard "ejs@npm:^3.1.9": - version: 3.1.9 - resolution: "ejs@npm:3.1.9" + version: 3.1.10 + resolution: "ejs@npm:3.1.10" dependencies: jake: ^10.8.5 bin: ejs: bin/cli.js - checksum: af6f10eb815885ff8a8cfacc42c6b6cf87daf97a4884f87a30e0c3271fedd85d76a3a297d9c33a70e735b97ee632887f85e32854b9cdd3a2d97edf931519a35f + checksum: ce90637e9c7538663ae023b8a7a380b2ef7cc4096de70be85abf5a3b9641912dde65353211d05e24d56b1f242d71185c6d00e02cb8860701d571786d92c71f05 languageName: node linkType: hard @@ -7791,12 +8138,12 @@ __metadata: linkType: hard "enhanced-resolve@npm:^5.12.0": - version: 5.15.0 - resolution: "enhanced-resolve@npm:5.15.0" + version: 5.17.0 + resolution: "enhanced-resolve@npm:5.17.0" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11 + checksum: 1066000454da6a7aeabdbe1f433d912d1e39e6892142a78a37b6577aab27e0436091fa1399d857ad87085b1c3b73a0f811c8874da3dbdc40fbd5ebe89a5568e6 languageName: node linkType: hard @@ -7824,7 +8171,7 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.2.0, entities@npm:^4.4.0": +"entities@npm:^4.2.0, entities@npm:^4.4.0, entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 @@ -7856,19 +8203,19 @@ __metadata: linkType: hard "env-var@npm:^7.4.1": - version: 7.4.1 - resolution: "env-var@npm:7.4.1" - checksum: 35cbb504d6b803d837a34b84bf9913905d5e627400aeef9529d3a0acd6af9e0b1f9d87b833ac30c76323bd97314e1890514e4ce795643f8a432f39990796e97d + version: 7.5.0 + resolution: "env-var@npm:7.5.0" + checksum: 7be2a834693cc1d03f3b86ca2d5899fa08cbdcdec3468368ada85c60f6dcd83dc166db3e5dd59f6a85a5e5995a9bdc648082a62dc6f33d8a2351f0ab7d9cab60 languageName: node linkType: hard "enzyme-shallow-equal@npm:^1.0.0": - version: 1.0.5 - resolution: "enzyme-shallow-equal@npm:1.0.5" + version: 1.0.7 + resolution: "enzyme-shallow-equal@npm:1.0.7" dependencies: - has: ^1.0.3 + hasown: ^2.0.0 object-is: ^1.1.5 - checksum: e18a728225b3ef501a223608955e2c8e915adf24dfe4d778bdbc89e4ecd80384723e9d44780176be1529f6b642e7837211f502bff89f62833d8f9cae027997e0 + checksum: ecbdf5a897ba33e699316f1456c7865b8140a6fc7916b700721964fe169e750be35f1fff5184a80e35b39e793523d678f4f4d12f48fce15145d206f5db01daa9 languageName: node linkType: hard @@ -7897,50 +8244,73 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" dependencies: - array-buffer-byte-length: ^1.0.0 - arraybuffer.prototype.slice: ^1.0.2 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.5 - es-set-tostringtag: ^2.0.1 + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + data-view-buffer: ^1.0.1 + data-view-byte-length: ^1.0.1 + data-view-byte-offset: ^1.0.0 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-set-tostringtag: ^2.0.3 es-to-primitive: ^1.2.1 function.prototype.name: ^1.1.6 - get-intrinsic: ^1.2.2 - get-symbol-description: ^1.0.0 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 globalthis: ^1.0.3 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 has-symbols: ^1.0.3 - hasown: ^2.0.0 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 + hasown: ^2.0.2 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 is-callable: ^1.2.7 - is-negative-zero: ^2.0.2 + is-data-view: ^1.0.1 + is-negative-zero: ^2.0.3 is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.2 + is-shared-array-buffer: ^1.0.3 is-string: ^1.0.7 - is-typed-array: ^1.1.12 + is-typed-array: ^1.1.13 is-weakref: ^1.0.2 object-inspect: ^1.13.1 object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.5.1 - safe-array-concat: ^1.0.1 - safe-regex-test: ^1.0.0 - string.prototype.trim: ^1.2.8 - string.prototype.trimend: ^1.0.7 - string.prototype.trimstart: ^1.0.7 - typed-array-buffer: ^1.0.0 - typed-array-byte-length: ^1.0.0 - typed-array-byte-offset: ^1.0.0 - typed-array-length: ^1.0.4 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.2 + safe-regex-test: ^1.0.3 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.8 + typed-array-buffer: ^1.0.2 + typed-array-byte-length: ^1.0.1 + typed-array-byte-offset: ^1.0.2 + typed-array-length: ^1.0.6 unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.13 - checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a + which-typed-array: ^1.1.15 + checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" + dependencies: + get-intrinsic: ^1.2.4 + checksum: f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 + languageName: node + linkType: hard + +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 languageName: node linkType: hard @@ -7961,40 +8331,49 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.12, es-iterator-helpers@npm:^1.0.15": - version: 1.0.15 - resolution: "es-iterator-helpers@npm:1.0.15" +"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.19": + version: 1.0.19 + resolution: "es-iterator-helpers@npm:1.0.19" dependencies: - asynciterator.prototype: ^1.0.0 - call-bind: ^1.0.2 + call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.22.1 - es-set-tostringtag: ^2.0.1 - function-bind: ^1.1.1 - get-intrinsic: ^1.2.1 + es-abstract: ^1.23.3 + es-errors: ^1.3.0 + es-set-tostringtag: ^2.0.3 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 globalthis: ^1.0.3 - has-property-descriptors: ^1.0.0 - has-proto: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 has-symbols: ^1.0.3 - internal-slot: ^1.0.5 + internal-slot: ^1.0.7 iterator.prototype: ^1.1.2 - safe-array-concat: ^1.0.1 - checksum: 50081ae5c549efe62e5c1d244df0194b40b075f7897fc2116b7e1aa437eb3c41f946d2afda18c33f9b31266ec544765932542765af839f76fa6d7b7855d1e0e1 + safe-array-concat: ^1.1.2 + checksum: 7ae112b88359fbaf4b9d7d1d1358ae57c5138768c57ba3a8fb930393662653b0512bfd7917c15890d1471577fb012fee8b73b4465e59b331739e6ee94f961683 languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.2 - resolution: "es-set-tostringtag@npm:2.0.2" +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" dependencies: - get-intrinsic: ^1.2.2 - has-tostringtag: ^1.0.0 - hasown: ^2.0.0 - checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + es-errors: ^1.3.0 + checksum: 26f0ff78ab93b63394e8403c353842b2272836968de4eafe97656adfb8a7c84b9099bf0fe96ed58f4a4cddc860f6e34c77f91649a58a5daa4a9c40b902744e3c languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0": +"es-set-tostringtag@npm:^2.0.1, es-set-tostringtag@npm:^2.0.3": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: ^1.2.4 + has-tostringtag: ^1.0.2 + hasown: ^2.0.1 + checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 + languageName: node + linkType: hard + +"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -8014,14 +8393,15 @@ __metadata: languageName: node linkType: hard -"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.46, es5-ext@npm:^0.10.50, es5-ext@npm:^0.10.53, es5-ext@npm:~0.10.14, es5-ext@npm:~0.10.2, es5-ext@npm:~0.10.46": - version: 0.10.62 - resolution: "es5-ext@npm:0.10.62" +"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.46, es5-ext@npm:^0.10.62, es5-ext@npm:^0.10.64, es5-ext@npm:~0.10.14, es5-ext@npm:~0.10.2": + version: 0.10.64 + resolution: "es5-ext@npm:0.10.64" dependencies: es6-iterator: ^2.0.3 es6-symbol: ^3.1.3 + esniff: ^2.0.1 next-tick: ^1.1.0 - checksum: 25f42f6068cfc6e393cf670bc5bba249132c5f5ec2dd0ed6e200e6274aca2fed8e9aec8a31c76031744c78ca283c57f0b41c7e737804c6328c7b8d3fbcba7983 + checksum: 01179fab0769fdbef213062222f99d0346724dbaccf04b87c0e6ee7f0c97edabf14be647ca1321f0497425ea7145de0fd278d1b3f3478864b8933e7136a5c645 languageName: node linkType: hard @@ -8037,12 +8417,12 @@ __metadata: linkType: hard "es6-symbol@npm:^3.1.1, es6-symbol@npm:^3.1.3": - version: 3.1.3 - resolution: "es6-symbol@npm:3.1.3" + version: 3.1.4 + resolution: "es6-symbol@npm:3.1.4" dependencies: - d: ^1.0.1 - ext: ^1.1.2 - checksum: cd49722c2a70f011eb02143ef1c8c70658d2660dead6641e160b94619f408b9cf66425515787ffe338affdf0285ad54f4eae30ea5bd510e33f8659ec53bcaa70 + d: ^1.0.2 + ext: ^1.7.0 + checksum: 52125ec4b5d1b6b93b8d3d42830bb19f8da21080ffcf45253b614bc6ff3e31349be202fb745d4d1af6778cdf5e38fea30e0c7e7dc37e2aecd44acc43502055f9 languageName: node linkType: hard @@ -8135,33 +8515,33 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.20.1": - version: 0.20.2 - resolution: "esbuild@npm:0.20.2" - dependencies: - "@esbuild/aix-ppc64": 0.20.2 - "@esbuild/android-arm": 0.20.2 - "@esbuild/android-arm64": 0.20.2 - "@esbuild/android-x64": 0.20.2 - "@esbuild/darwin-arm64": 0.20.2 - "@esbuild/darwin-x64": 0.20.2 - "@esbuild/freebsd-arm64": 0.20.2 - "@esbuild/freebsd-x64": 0.20.2 - "@esbuild/linux-arm": 0.20.2 - "@esbuild/linux-arm64": 0.20.2 - "@esbuild/linux-ia32": 0.20.2 - "@esbuild/linux-loong64": 0.20.2 - "@esbuild/linux-mips64el": 0.20.2 - "@esbuild/linux-ppc64": 0.20.2 - "@esbuild/linux-riscv64": 0.20.2 - "@esbuild/linux-s390x": 0.20.2 - "@esbuild/linux-x64": 0.20.2 - "@esbuild/netbsd-x64": 0.20.2 - "@esbuild/openbsd-x64": 0.20.2 - "@esbuild/sunos-x64": 0.20.2 - "@esbuild/win32-arm64": 0.20.2 - "@esbuild/win32-ia32": 0.20.2 - "@esbuild/win32-x64": 0.20.2 +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": 0.21.5 + "@esbuild/android-arm": 0.21.5 + "@esbuild/android-arm64": 0.21.5 + "@esbuild/android-x64": 0.21.5 + "@esbuild/darwin-arm64": 0.21.5 + "@esbuild/darwin-x64": 0.21.5 + "@esbuild/freebsd-arm64": 0.21.5 + "@esbuild/freebsd-x64": 0.21.5 + "@esbuild/linux-arm": 0.21.5 + "@esbuild/linux-arm64": 0.21.5 + "@esbuild/linux-ia32": 0.21.5 + "@esbuild/linux-loong64": 0.21.5 + "@esbuild/linux-mips64el": 0.21.5 + "@esbuild/linux-ppc64": 0.21.5 + "@esbuild/linux-riscv64": 0.21.5 + "@esbuild/linux-s390x": 0.21.5 + "@esbuild/linux-x64": 0.21.5 + "@esbuild/netbsd-x64": 0.21.5 + "@esbuild/openbsd-x64": 0.21.5 + "@esbuild/sunos-x64": 0.21.5 + "@esbuild/win32-arm64": 0.21.5 + "@esbuild/win32-ia32": 0.21.5 + "@esbuild/win32-x64": 0.21.5 dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -8211,14 +8591,14 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: bc88050fc1ca5c1bd03648f9979e514bdefb956a63aa3974373bb7b9cbac0b3aac9b9da1b5bdca0b3490e39d6b451c72815dbd6b7d7f978c91fbe9c9e9aa4e4c + checksum: 2911c7b50b23a9df59a7d6d4cdd3a4f85855787f374dce751148dbb13305e0ce7e880dde1608c2ab7a927fc6cec3587b80995f7fc87a64b455f8b70b55fd8ec1 languageName: node linkType: hard "escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 1ec0977aa2772075493002bdbd549d595ff6e9393b1cb0d7d6fcaf78c750da0c158f180938365486f75cb69fba20294351caddfce1b46552a7b6c3cde52eaa02 languageName: node linkType: hard @@ -8257,16 +8637,18 @@ __metadata: languageName: node linkType: hard -"eslint-compat-utils@npm:^0.1.2": - version: 0.1.2 - resolution: "eslint-compat-utils@npm:0.1.2" +"eslint-compat-utils@npm:^0.5.1": + version: 0.5.1 + resolution: "eslint-compat-utils@npm:0.5.1" + dependencies: + semver: ^7.5.4 peerDependencies: eslint: ">=6.0.0" - checksum: 2315d9db81efb7f58808053bf32a1d5970b38e01cd8244f4f1b5aa05d883255c5c93fc184e9c29a0e7e2dcf16ff16330977302474d3fa870e41c5bed9c66f76b + checksum: beccf2a5bd7c7974e3584b269f8a02667c83bca64cfd4c866f3055867f187e78b00ee826721765bdee9b13efaaa248f8068c581f7bb05803e8f47abb116e68fc languageName: node linkType: hard -"eslint-config-next@npm:^13.4.19": +"eslint-config-next@npm:^13.5.6": version: 13.5.6 resolution: "eslint-config-next@npm:13.5.6" dependencies: @@ -8290,12 +8672,12 @@ __metadata: linkType: hard "eslint-config-next@npm:latest": - version: 14.0.4 - resolution: "eslint-config-next@npm:14.0.4" + version: 14.2.4 + resolution: "eslint-config-next@npm:14.2.4" dependencies: - "@next/eslint-plugin-next": 14.0.4 + "@next/eslint-plugin-next": 14.2.4 "@rushstack/eslint-patch": ^1.3.3 - "@typescript-eslint/parser": ^5.4.2 || ^6.0.0 + "@typescript-eslint/parser": ^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0 eslint-import-resolver-node: ^0.3.6 eslint-import-resolver-typescript: ^3.5.2 eslint-plugin-import: ^2.28.1 @@ -8308,7 +8690,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 6abb85c2dde8e2a49042d31e85ba6ebccbfd3f6576f470a8df6842afebb1ec14c89ae485cfb9c490df830c7ada55a8bcf7547936def13c5e483f4b882a281cab + checksum: 408ab113ecfdfa2de376ef9d23445cb80b66090ef3ab69b5ff4e5d14e83e85f9671a2edb05c8fced9555f6f3602ab0095579facef67ea50dba066a2156d201da languageName: node linkType: hard @@ -8334,7 +8716,7 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-typescript@npm:^3.5.2, eslint-import-resolver-typescript@npm:^3.6.0": +"eslint-import-resolver-typescript@npm:^3.5.2, eslint-import-resolver-typescript@npm:^3.6.1": version: 3.6.1 resolution: "eslint-import-resolver-typescript@npm:3.6.1" dependencies: @@ -8353,42 +8735,54 @@ __metadata: linkType: hard "eslint-module-utils@npm:^2.7.4, eslint-module-utils@npm:^2.8.0": - version: 2.8.0 - resolution: "eslint-module-utils@npm:2.8.0" + version: 2.8.1 + resolution: "eslint-module-utils@npm:2.8.1" dependencies: debug: ^3.2.7 peerDependenciesMeta: eslint: optional: true - checksum: 74c6dfea7641ebcfe174be61168541a11a14aa8d72e515f5f09af55cd0d0862686104b0524aa4b8e0ce66418a44aa38a94d2588743db5fd07a6b49ffd16921d2 + checksum: 3cecd99b6baf45ffc269167da0f95dcb75e5aa67b93d73a3bab63e2a7eedd9cdd6f188eed048e2f57c1b77db82c9cbf2adac20b512fa70e597d863dd3720170d languageName: node linkType: hard "eslint-plugin-cypress@npm:^2.15.1": - version: 2.15.1 - resolution: "eslint-plugin-cypress@npm:2.15.1" + version: 2.15.2 + resolution: "eslint-plugin-cypress@npm:2.15.2" dependencies: globals: ^13.20.0 peerDependencies: eslint: ">= 3.2.1" - checksum: 3e66fa9a943fff52eaf3758250a63c2a0f8ffd60c50572beaf3688b33a55fbf0060d18ef32bc26abb57aef070517db827c22fd3d607582861d464970f95e550e + checksum: 0ffd8b9b39a22543917e2d9ae0cb7545ce5ea0eea171d947b6e015062f462bf66a208b7e711923d5ad1525f3fb03a3f35c7d978ab88352343302ea885ee98c1b languageName: node linkType: hard "eslint-plugin-es-x@npm:^7.5.0": - version: 7.5.0 - resolution: "eslint-plugin-es-x@npm:7.5.0" + version: 7.7.0 + resolution: "eslint-plugin-es-x@npm:7.7.0" dependencies: "@eslint-community/eslint-utils": ^4.1.2 "@eslint-community/regexpp": ^4.6.0 - eslint-compat-utils: ^0.1.2 + eslint-compat-utils: ^0.5.1 peerDependencies: eslint: ">=8" - checksum: e770e57df78c3c38582de9bc4b9632ec5101a6dae8ac84f6ac219e8d8eb137f943db9730e037cfbc82f5d3ab6358e1b494fa6c628f425ebfc7e3094d5aa9d223 + checksum: 55621d2ddf8271654140c596682883d670ca64657a50af3de6b1a9bfb5fc16384591092f02974ca58cf52b1a2cf0042c8d16226dfd24c1d7f1893d5a0288d973 + languageName: node + linkType: hard + +"eslint-plugin-es@npm:^3.0.0": + version: 3.0.1 + resolution: "eslint-plugin-es@npm:3.0.1" + dependencies: + eslint-utils: ^2.0.0 + regexpp: ^3.0.0 + peerDependencies: + eslint: ">=4.19.1" + checksum: e57592c52301ee8ddc296ae44216df007f3a870bcb3be8d1fbdb909a1d3a3efe3fa3785de02066f9eba1d6466b722d3eb3cc3f8b75b3cf6a1cbded31ac6298e4 languageName: node linkType: hard -"eslint-plugin-import@npm:^2.28.1": +"eslint-plugin-import@npm:^2.28.1, eslint-plugin-import@npm:^2.29.1": version: 2.29.1 resolution: "eslint-plugin-import@npm:2.29.1" dependencies: @@ -8441,9 +8835,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-n@npm:^16.1.0": - version: 16.6.1 - resolution: "eslint-plugin-n@npm:16.6.1" +"eslint-plugin-n@npm:^16.6.2": + version: 16.6.2 + resolution: "eslint-plugin-n@npm:16.6.2" dependencies: "@eslint-community/eslint-utils": ^4.4.0 builtins: ^5.0.1 @@ -8458,7 +8852,23 @@ __metadata: semver: ^7.5.3 peerDependencies: eslint: ">=7.0.0" - checksum: 2c8e80cf07f669be287bf7af335dd450c2f0c08e4efcf8ef8ccd7d1aa9d2e93dfa20f9f204efa22e4a552057e54b7cc6597bbf9dbb5626b1d711e41054ed46ef + checksum: 3b468da0038cf25af582608983491b33ac2d481b6a94a0ff2e715d3b85e1ff8cb93df4cd67b689d520bea1bfb8f2b717f01606bf6b2ea19fe8f9c0999ea7057d + languageName: node + linkType: hard + +"eslint-plugin-node@npm:^11.1.0": + version: 11.1.0 + resolution: "eslint-plugin-node@npm:11.1.0" + dependencies: + eslint-plugin-es: ^3.0.0 + eslint-utils: ^2.0.0 + ignore: ^5.1.1 + minimatch: ^3.0.4 + resolve: ^1.10.1 + semver: ^6.1.0 + peerDependencies: + eslint: ">=5.16.0" + checksum: 5804c4f8a6e721f183ef31d46fbe3b4e1265832f352810060e0502aeac7de034df83352fc88643b19641bb2163f2587f1bd4119aff0fd21e8d98c57c450e013b languageName: node linkType: hard @@ -8472,52 +8882,54 @@ __metadata: linkType: hard "eslint-plugin-react@npm:^7.33.2": - version: 7.33.2 - resolution: "eslint-plugin-react@npm:7.33.2" + version: 7.34.3 + resolution: "eslint-plugin-react@npm:7.34.3" dependencies: - array-includes: ^3.1.6 - array.prototype.flatmap: ^1.3.1 - array.prototype.tosorted: ^1.1.1 + array-includes: ^3.1.8 + array.prototype.findlast: ^1.2.5 + array.prototype.flatmap: ^1.3.2 + array.prototype.toreversed: ^1.1.2 + array.prototype.tosorted: ^1.1.4 doctrine: ^2.1.0 - es-iterator-helpers: ^1.0.12 + es-iterator-helpers: ^1.0.19 estraverse: ^5.3.0 jsx-ast-utils: ^2.4.1 || ^3.0.0 minimatch: ^3.1.2 - object.entries: ^1.1.6 - object.fromentries: ^2.0.6 - object.hasown: ^1.1.2 - object.values: ^1.1.6 + object.entries: ^1.1.8 + object.fromentries: ^2.0.8 + object.hasown: ^1.1.4 + object.values: ^1.2.0 prop-types: ^15.8.1 - resolve: ^2.0.0-next.4 + resolve: ^2.0.0-next.5 semver: ^6.3.1 - string.prototype.matchall: ^4.0.8 + string.prototype.matchall: ^4.0.11 peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: b4c3d76390b0ae6b6f9fed78170604cc2c04b48e6778a637db339e8e3911ec9ef22510b0ae77c429698151d0f1b245f282177f384105b6830e7b29b9c9b26610 + checksum: 1a519b9792ab9392a5157f2543ce98ab1218c62f4a31c4c3ceb5dd3e7997def4aa07ab39f7276af0fe116ef002db29d97216a15b7aa3b200e55b641cf77d6292 languageName: node linkType: hard -"eslint-plugin-simple-import-sort@npm:^10.0.0": - version: 10.0.0 - resolution: "eslint-plugin-simple-import-sort@npm:10.0.0" +"eslint-plugin-simple-import-sort@npm:^12.1.0": + version: 12.1.0 + resolution: "eslint-plugin-simple-import-sort@npm:12.1.0" peerDependencies: eslint: ">=5.0.0" - checksum: 23221ff63f80f9c52da807d388ee8a51bc36a3b73345f60ec886e7973c28d75eb1d1e47f7f2916a7c1f94a1b5037b1450356a64a8fbd58096fd6bee57c6e3e48 + checksum: 8ba651c8d86359107130e99d11a839fe2b66647731c9582b74657fcfab2ea61fdf85621651f26aab5f8cbfe7516ea0c5d4d8fdcd68c3f9b7115d292f16ed3dde languageName: node linkType: hard -"eslint-plugin-unused-imports@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-plugin-unused-imports@npm:3.0.0" +"eslint-plugin-unused-imports@npm:^3.2.0": + version: 3.2.0 + resolution: "eslint-plugin-unused-imports@npm:3.2.0" dependencies: eslint-rule-composer: ^0.3.0 peerDependencies: - "@typescript-eslint/eslint-plugin": ^6.0.0 - eslint: ^8.0.0 + "@typescript-eslint/eslint-plugin": 6 - 7 + eslint: 8 peerDependenciesMeta: "@typescript-eslint/eslint-plugin": optional: true - checksum: 51666f62cc8dccba2895ced83f3c1e0b78b68c357e17360e156c4db548bfdeda34cbd8725192fb4903f22d5069400fb22ded6039631df01ee82fd618dc307247 + checksum: e85ae4f3af489294ef5e0969ab904fa87f9fa7c959ca0804f30845438db4aeb0428ddad7ab06a70608e93121626799977241b442fdf126a4d0667be57390c3d6 languageName: node linkType: hard @@ -8557,6 +8969,22 @@ __metadata: languageName: node linkType: hard +"eslint-utils@npm:^2.0.0": + version: 2.1.0 + resolution: "eslint-utils@npm:2.1.0" + dependencies: + eslint-visitor-keys: ^1.1.0 + checksum: 27500938f348da42100d9e6ad03ae29b3de19ba757ae1a7f4a087bdcf83ac60949bbb54286492ca61fac1f5f3ac8692dd21537ce6214240bf95ad0122f24d71d + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^1.1.0": + version: 1.3.0 + resolution: "eslint-visitor-keys@npm:1.3.0" + checksum: 37a19b712f42f4c9027e8ba98c2b06031c17e0c0a4c696cd429bd9ee04eb43889c446f2cd545e1ff51bef9593fcec94ecd2c2ef89129fcbbf3adadbef520376a + languageName: node + linkType: hard + "eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" @@ -8564,15 +8992,15 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.49.0, eslint@npm:^8.50.0": - version: 8.56.0 - resolution: "eslint@npm:8.56.0" +"eslint@npm:^8.50.0, eslint@npm:^8.57.0": + version: 8.57.0 + resolution: "eslint@npm:8.57.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.56.0 - "@humanwhocodes/config-array": ^0.11.13 + "@eslint/js": 8.57.0 + "@humanwhocodes/config-array": ^0.11.14 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 "@ungap/structured-clone": ^1.2.0 @@ -8608,7 +9036,19 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 + checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + languageName: node + linkType: hard + +"esniff@npm:^2.0.1": + version: 2.0.1 + resolution: "esniff@npm:2.0.1" + dependencies: + d: ^1.0.1 + es5-ext: ^0.10.62 + event-emitter: ^0.3.5 + type: ^2.7.2 + checksum: d814c0e5c39bce9925b2e65b6d8767af72c9b54f35a65f9f3d6e8c606dce9aebe35a9599d30f15b0807743f88689f445163cfb577a425de4fb8c3c5bc16710cc languageName: node linkType: hard @@ -8884,15 +9324,15 @@ __metadata: linkType: hard "express@npm:^4.18.2": - version: 4.18.2 - resolution: "express@npm:4.18.2" + version: 4.19.2 + resolution: "express@npm:4.19.2" dependencies: accepts: ~1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.1 + body-parser: 1.20.2 content-disposition: 0.5.4 content-type: ~1.0.4 - cookie: 0.5.0 + cookie: 0.6.0 cookie-signature: 1.0.6 debug: 2.6.9 depd: 2.0.0 @@ -8918,11 +9358,11 @@ __metadata: type-is: ~1.6.18 utils-merge: 1.0.1 vary: ~1.1.2 - checksum: 3c4b9b076879442f6b968fe53d85d9f1eeacbb4f4c41e5f16cc36d77ce39a2b0d81b3f250514982110d815b2f7173f5561367f9110fcc541f9371948e8c8b037 + checksum: 212dbd6c2c222a96a61bc927639c95970a53b06257080bb9e2838adb3bffdb966856551fdad1ab5dd654a217c35db94f987d0aa88d48fb04d306340f5f34dca5 languageName: node linkType: hard -"ext@npm:^1.1.2": +"ext@npm:^1.7.0": version: 1.7.0 resolution: "ext@npm:1.7.0" dependencies: @@ -8995,9 +9435,9 @@ __metadata: linkType: hard "fast-copy@npm:^3.0.0": - version: 3.0.1 - resolution: "fast-copy@npm:3.0.1" - checksum: 5496b5cf47df29eea479deef03b6b7188626a2cbc356b3015649062846729de6f1a9f555f937e772da8feae0a1231fab13096ed32424b2d61e4d065abc9969fe + version: 3.0.2 + resolution: "fast-copy@npm:3.0.2" + checksum: 47f584bcede08ab3198559d3e0e093a547d567715b86be2198da6e3366c3c73eed550d97b86f9fb90dae179982b89c15d68187def960f522cdce14bacdfc6184 languageName: node linkType: hard @@ -9043,17 +9483,17 @@ __metadata: linkType: hard "fast-json-stringify@npm:^5.7.0, fast-json-stringify@npm:^5.8.0": - version: 5.9.2 - resolution: "fast-json-stringify@npm:5.9.2" + version: 5.16.0 + resolution: "fast-json-stringify@npm:5.16.0" dependencies: - "@fastify/deepmerge": ^1.0.0 + "@fastify/merge-json-schemas": ^0.1.0 ajv: ^8.10.0 - ajv-formats: ^2.1.1 + ajv-formats: ^3.0.1 fast-deep-equal: ^3.1.3 fast-uri: ^2.1.0 json-schema-ref-resolver: ^1.0.1 rfdc: ^1.2.0 - checksum: a182986a60fed44239bc6efbd770d6832444068927bc64ca7da80e344b02ab31e681f681e041f9d31c0dc243d683037d6b01b71f523c9a7f5ff8fbb95c6cf94f + checksum: b2eaf3843d6337d65c31f90afb0db9a19d710e363c9d57fec3c1a50087189264174efcbde6c96eb5cbff1be2f739a59284bd7ce1a87dcb38e600e250051581ea languageName: node linkType: hard @@ -9081,9 +9521,9 @@ __metadata: linkType: hard "fast-redact@npm:^3.1.1": - version: 3.3.0 - resolution: "fast-redact@npm:3.3.0" - checksum: 3f7becc70a5a2662a9cbfdc52a4291594f62ae998806ee00315af307f32d9559dbf512146259a22739ee34401950ef47598c1f4777d33b0ed5027203d67f549c + version: 3.5.0 + resolution: "fast-redact@npm:3.5.0" + checksum: ef03f0d1849da074a520a531ad299bf346417b790a643931ab4e01cb72275c8d55b60dc8512fb1f1818647b696790edefaa96704228db9f012da935faa1940af languageName: node linkType: hard @@ -9102,9 +9542,9 @@ __metadata: linkType: hard "fast-uri@npm:^2.0.0, fast-uri@npm:^2.1.0": - version: 2.3.0 - resolution: "fast-uri@npm:2.3.0" - checksum: 92c8975a60cf0bb5344197559b1a89b8743b9ff9254aeea217d7df63606d79e8673a0d892eee7b953c4b62bf3b900b95cbfe64f0285dde41e7bd2f111123f48b + version: 2.4.0 + resolution: "fast-uri@npm:2.4.0" + checksum: 027633ccff61122bcfc2c3f45741a9e41fd68c365eb85ff8f69b305aa3918c25283daba86687e7c938aa0b0c7134c7142330722ee9fd5e0a9702fbff031fa569 languageName: node linkType: hard @@ -9130,47 +9570,47 @@ __metadata: linkType: hard "fastify-type-provider-zod@npm:^1.1.9": - version: 1.1.9 - resolution: "fastify-type-provider-zod@npm:1.1.9" + version: 1.2.0 + resolution: "fastify-type-provider-zod@npm:1.2.0" dependencies: - zod-to-json-schema: ^3.17.1 + zod-to-json-schema: ^3.23.0 peerDependencies: fastify: ^4.0.0 zod: ^3.14.2 - checksum: 86792031057cf3807a2e77ef41b16161d94c89ab95bd6284574502351df9c4d1e1621d4f7e7f3f14cd81aec9923c3a4f61c8889d5abb3b57e52ee9c0015056e1 + checksum: d37b3a1be78291a78ca162508f85db96f839e875ee3e760b8ac1cc7b12b631943c250399435d443610d79d83b67075ddc7b4b1d6d19b7aa3177a31cdb3799511 languageName: node linkType: hard "fastify@npm:^4.23.2": - version: 4.25.2 - resolution: "fastify@npm:4.25.2" + version: 4.28.0 + resolution: "fastify@npm:4.28.0" dependencies: "@fastify/ajv-compiler": ^3.5.0 "@fastify/error": ^3.4.0 "@fastify/fast-json-stringify-compiler": ^4.3.0 abstract-logging: ^2.0.1 - avvio: ^8.2.1 + avvio: ^8.3.0 fast-content-type-parse: ^1.1.0 fast-json-stringify: ^5.8.0 - find-my-way: ^7.7.0 + find-my-way: ^8.0.0 light-my-request: ^5.11.0 - pino: ^8.17.0 + pino: ^9.0.0 process-warning: ^3.0.0 proxy-addr: ^2.0.7 rfdc: ^1.3.0 secure-json-parse: ^2.7.0 semver: ^7.5.4 toad-cache: ^3.3.0 - checksum: 63158f3639de23751cb1b13eae9dfe211bd9295a0f74a0f4ddc12a0a82efcf2f86a404bd0c1c83c2b58e153ec23611576c1b1917da7679e12ef1093fdc8bbd64 + checksum: 36944ecd39fb0ea364cfbbf2d2df7caf5979d1c663e0f4ae91f6aa4de37fd9909bce26aea724cc313e26632294b78669954b965ea9678defc22907a535afb565 languageName: node linkType: hard -"fastq@npm:^1.6.0, fastq@npm:^1.6.1": - version: 1.16.0 - resolution: "fastq@npm:1.16.0" +"fastq@npm:^1.17.1, fastq@npm:^1.6.0": + version: 1.17.1 + resolution: "fastq@npm:1.17.1" dependencies: reusify: ^1.0.4 - checksum: 1d40ed1f100ae625e5720484e8602b7ad07649370f1cbc3e34a6b9630a0bfed6946bab0322d8a368a1e3cde87bb9bbb8d3bc2ae01a0c1f022fac1d07c04e4feb + checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 languageName: node linkType: hard @@ -9250,12 +9690,12 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 languageName: node linkType: hard @@ -9274,14 +9714,14 @@ __metadata: languageName: node linkType: hard -"find-my-way@npm:^7.7.0": - version: 7.7.0 - resolution: "find-my-way@npm:7.7.0" +"find-my-way@npm:^8.0.0": + version: 8.2.0 + resolution: "find-my-way@npm:8.2.0" dependencies: fast-deep-equal: ^3.1.3 fast-querystring: ^1.0.0 - safe-regex2: ^2.0.0 - checksum: 6cd3fbfd57aa359475658bbc2336b27c561c16a91a1fb6346d025e3d6ff7a127fdc4cf23ac4b6ed8054534ac45f63a5b9421d52834ae1d36c47ccfde2a73a3aa + safe-regex2: ^3.1.0 + checksum: 4f59fe17a1431511ec172403da0d1ac05bf9efebfdd4c7149b658d748b2570b63d798847e08ceea00f57543611fdb64ba3793dfc67a9ed7b5bfa0d77c8693eb5 languageName: node linkType: hard @@ -9352,9 +9792,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 languageName: node linkType: hard @@ -9365,22 +9805,22 @@ __metadata: languageName: node linkType: hard -"focus-lock@npm:^1.0.0": - version: 1.0.0 - resolution: "focus-lock@npm:1.0.0" +"focus-lock@npm:^1.3.5": + version: 1.3.5 + resolution: "focus-lock@npm:1.3.5" dependencies: tslib: ^2.0.3 - checksum: 85eb62534e8c0314026453c4f734bf6450054a19b248280f3f69c98b5d5481707124e2206d7dc515650a6f28da827a2de297455056a9c8f398e5f8ba5dba8419 + checksum: 09fb0e4402694aabafa8f7d49a656f683bbf39c94efc0c0240934d880792ef86d8c11bb7d77ef6f5d68ccfdfb7f191ecc2b38a259182a6791bcf96860a408d1c languageName: node linkType: hard -"follow-redirects@npm:^1.15.0": - version: 1.15.4 - resolution: "follow-redirects@npm:1.15.4" +"follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: debug: optional: true - checksum: e178d1deff8b23d5d24ec3f7a94cde6e47d74d0dc649c35fc9857041267c12ec5d44650a0c5597ef83056ada9ea6ca0c30e7c4f97dbf07d035086be9e6a5b7b6 + checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5 languageName: node linkType: hard @@ -9394,12 +9834,12 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" + version: 3.2.1 + resolution: "foreground-child@npm:3.2.1" dependencies: cross-spawn: ^7.0.0 signal-exit: ^4.0.1 - checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + checksum: 3e2e844d6003c96d70affe8ae98d7eaaba269a868c14d997620c088340a8775cd5d2d9043e6ceebae1928d8d9a874911c4d664b9a267e8995945df20337aebc0 languageName: node linkType: hard @@ -9477,8 +9917,8 @@ __metadata: linkType: hard "formik@npm:^2.4.5": - version: 2.4.5 - resolution: "formik@npm:2.4.5" + version: 2.4.6 + resolution: "formik@npm:2.4.6" dependencies: "@types/hoist-non-react-statics": ^3.3.1 deepmerge: ^2.1.1 @@ -9490,7 +9930,7 @@ __metadata: tslib: ^2.0.0 peerDependencies: react: ">=16.8.0" - checksum: 316c91fc4e440094655c0d0ba47277a0f84f6082f77ae2ae959e97e2eebb8eab5b866a9e43d93a28efdae07c3f23e779da67922e2f2a1fb47d135b7346e0b5f3 + checksum: ed0ff8eca11b3c4b5564a6ae5650cb124820d239ece9a7cb3d526ff8ce3d8f9fb992e2f78ef0666e65b7c05c944a91cc98a736e806e424019d6aac8bee313a42 languageName: node linkType: hard @@ -9607,7 +10047,7 @@ __metadata: languageName: node linkType: hard -"fs-minipass@npm:^3.0.0, fs-minipass@npm:^3.0.2": +"fs-minipass@npm:^3.0.0, fs-minipass@npm:^3.0.3": version: 3.0.3 resolution: "fs-minipass@npm:3.0.3" dependencies: @@ -9642,7 +10082,7 @@ __metadata: languageName: node linkType: hard -"function-bind@npm:^1.1.1, function-bind@npm:^1.1.2": +"function-bind@npm:^1.1.2": version: 1.1.2 resolution: "function-bind@npm:1.1.2" checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 @@ -9685,8 +10125,8 @@ __metadata: linkType: hard "gauge@npm:^5.0.0": - version: 5.0.1 - resolution: "gauge@npm:5.0.1" + version: 5.0.2 + resolution: "gauge@npm:5.0.2" dependencies: aproba: ^1.0.3 || ^2.0.0 color-support: ^1.1.3 @@ -9696,7 +10136,7 @@ __metadata: string-width: ^4.2.3 strip-ansi: ^6.0.1 wide-align: ^1.1.5 - checksum: 09b1eb8d8c850df7e4e2822feef27427afc845d4839fa13a08ddad74f882caf668dd1e77ac5e059d3e9a7b0cef59b706d28be40e1dc5fd326da32965e1f206a6 + checksum: bc51e4f849bce385e51047d5f372fd15e04b8d41abf63b32cc29587678542570eab9694e4ebeb9afa9ff77440eeceb427296409a7c181ce502222a8856f225c6 languageName: node linkType: hard @@ -9728,15 +10168,16 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": - version: 1.2.2 - resolution: "get-intrinsic@npm:1.2.2" +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" dependencies: + es-errors: ^1.3.0 function-bind: ^1.1.2 has-proto: ^1.0.1 has-symbols: ^1.0.3 hasown: ^2.0.0 - checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 + checksum: 414e3cdf2c203d1b9d7d33111df746a4512a1aa622770b361dadddf8ed0b5aeb26c560f49ca077e24bfafb0acb55ca908d1f709216ccba33ffc548ec8a79a951 languageName: node linkType: hard @@ -9777,22 +10218,23 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" +"get-symbol-description@npm:^1.0.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 + call-bind: ^1.0.5 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + checksum: e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 languageName: node linkType: hard "get-tsconfig@npm:^4.5.0, get-tsconfig@npm:^4.7.0": - version: 4.7.2 - resolution: "get-tsconfig@npm:4.7.2" + version: 4.7.5 + resolution: "get-tsconfig@npm:4.7.5" dependencies: resolve-pkg-maps: ^1.0.0 - checksum: 172358903250eff0103943f816e8a4e51d29b8e5449058bdf7266714a908a48239f6884308bd3a6ff28b09f692b9533dbebfd183ab63e4e14f073cda91f1bca9 + checksum: e5b271fae2b4cd1869bbfc58db56983026cc4a08fdba988725a6edd55d04101507de154722503a22ee35920898ff9bdcba71f99d93b17df35dddb8e8a2ad91be languageName: node linkType: hard @@ -9868,10 +10310,18 @@ __metadata: languageName: node linkType: hard -"glob-to-regexp@npm:^0.4.1": - version: 0.4.1 - resolution: "glob-to-regexp@npm:0.4.1" - checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 +"glob@npm:10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 languageName: node linkType: hard @@ -9889,18 +10339,19 @@ __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": - version: 10.3.10 - resolution: "glob@npm:10.3.10" +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.3": + version: 10.4.2 + resolution: "glob@npm:10.4.2" dependencies: foreground-child: ^3.1.0 - jackspeak: ^2.3.5 - minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 + jackspeak: ^3.1.2 + minimatch: ^9.0.4 + minipass: ^7.1.2 + package-json-from-dist: ^1.0.0 + path-scurry: ^1.11.1 bin: glob: dist/esm/bin.mjs - checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + checksum: bd7c0e30701136e936f414e5f6f82c7f04503f01df77408f177aa584927412f0bde0338e6ec541618cd21eacc57dde33e7b3c6c0a779cc1c6e6a0e14f3d15d9b languageName: node linkType: hard @@ -9917,7 +10368,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: @@ -9972,6 +10423,13 @@ __metadata: languageName: node linkType: hard +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e + languageName: node + linkType: hard + "globals@npm:^13.19.0, globals@npm:^13.20.0, globals@npm:^13.24.0": version: 13.24.0 resolution: "globals@npm:13.24.0" @@ -9982,11 +10440,12 @@ __metadata: linkType: hard "globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: ^1.1.3 - checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 + define-properties: ^1.2.1 + gopd: ^1.0.1 + checksum: 39ad667ad9f01476474633a1834a70842041f70a55571e8dcef5fb957980a92da5022db5430fca8aecc5d47704ae30618c0bc877a579c70710c904e9ef06108a languageName: node linkType: hard @@ -10018,16 +10477,16 @@ __metadata: linkType: hard "globby@npm:^14.0.0": - version: 14.0.0 - resolution: "globby@npm:14.0.0" + version: 14.0.1 + resolution: "globby@npm:14.0.1" dependencies: - "@sindresorhus/merge-streams": ^1.0.0 + "@sindresorhus/merge-streams": ^2.1.0 fast-glob: ^3.3.2 ignore: ^5.2.4 path-type: ^5.0.0 slash: ^5.1.0 unicorn-magic: ^0.1.0 - checksum: f331b42993e420c8f2b61a6ca062276977ea6d95f181640ff018f00200f4fe5b50f1fae7540903483e6570ca626fe16234ab88e848d43381a2529220548a9d39 + checksum: 33568444289afb1135ad62d52d5e8412900cec620e3b6ece533afa46d004066f14b97052b643833d7cf4ee03e7fac571430130cde44c333df91a45d313105170 languageName: node linkType: hard @@ -10176,19 +10635,19 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0": - version: 1.0.1 - resolution: "has-property-descriptors@npm:1.0.1" +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" dependencies: - get-intrinsic: ^1.2.2 - checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 + es-define-property: ^1.0.0 + checksum: fcbb246ea2838058be39887935231c6d5788babed499d0e9d0cc5737494c48aba4fe17ba1449e0d0fbbb1e36175442faa37f9c427ae357d6ccb1d895fbcd3de3 languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 languageName: node linkType: hard @@ -10199,12 +10658,12 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" dependencies: - has-symbols: ^1.0.2 - checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + has-symbols: ^1.0.3 + checksum: 999d60bb753ad714356b2c6c87b7fb74f32463b8426e159397da4bde5bca7e598ab1073f4d8d4deafac297f2eb311484cd177af242776bf05f0d11565680468d languageName: node linkType: hard @@ -10215,19 +10674,12 @@ __metadata: languageName: node linkType: hard -"has@npm:^1.0.3": - version: 1.0.4 - resolution: "has@npm:1.0.4" - checksum: 8a11ba062e0627c9578a1d08285401e39f1d071a9692ddf793199070edb5648b21c774dd733e2a181edd635bf6862731885f476f4ccf67c998d7a5ff7cef2550 - languageName: node - linkType: hard - -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: function-bind: ^1.1.2 - checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + checksum: e8516f776a15149ca6c6ed2ae3110c417a00b62260e222590e54aa367cbcd6ed99122020b37b7fbdf05748df57b265e70095d7bf35a47660587619b15ffb93db languageName: node linkType: hard @@ -10310,11 +10762,11 @@ __metadata: linkType: hard "hosted-git-info@npm:^7.0.0": - version: 7.0.1 - resolution: "hosted-git-info@npm:7.0.1" + version: 7.0.2 + resolution: "hosted-git-info@npm:7.0.2" dependencies: lru-cache: ^10.0.1 - checksum: be5280f0a20d6153b47e1ab578e09f5ae8ad734301b3ed7e547dc88a6814d7347a4888db1b4f9635cc738e3c0ef1fbff02272aba7d07c75d4c5a50ff8d618db6 + checksum: 467cf908a56556417b18e86ae3b8dee03c2360ef1d51e61c4028fe87f6f309b6ff038589c94b5666af207da9d972d5107698906aabeb78aca134641962a5c6f8 languageName: node linkType: hard @@ -10422,6 +10874,18 @@ __metadata: languageName: node linkType: hard +"htmlparser2@npm:^9.1.0": + version: 9.1.0 + resolution: "htmlparser2@npm:9.1.0" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + domutils: ^3.1.0 + entities: ^4.5.0 + checksum: e5f8d5193967e4a500226f37bdf2c0f858cecb39dde14d0439f24bf2c461a4342778740d988fbaba652b0e4cb6052f7f2e99e69fc1a329a86c629032bb76e7c8 + 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": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -10454,12 +10918,12 @@ __metadata: linkType: hard "http-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "http-proxy-agent@npm:7.0.0" + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" dependencies: agent-base: ^7.1.0 debug: ^4.3.4 - checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 languageName: node linkType: hard @@ -10516,12 +10980,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.0, https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": - version: 7.0.2 - resolution: "https-proxy-agent@npm:7.0.2" + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" dependencies: agent-base: ^7.0.2 debug: 4 - checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 languageName: node linkType: hard @@ -10579,9 +11043,9 @@ __metadata: linkType: hard "hyphenate-style-name@npm:^1.0.3": - version: 1.0.4 - resolution: "hyphenate-style-name@npm:1.0.4" - checksum: 4f5bf4b055089754924babebaa23c17845937bcca6aee95d5d015f8fa1e6814279002bd6a9e541e3fac2cd02519fc76305396727066c57c8e21a7e73e7a12137 + version: 1.1.0 + resolution: "hyphenate-style-name@npm:1.1.0" + checksum: b9ed74e29181d96bd58a2d0e62fc4a19879db591dba268275829ff0ae595fcdf11faafaeaa63330a45c3004664d7db1f0fc7cdb372af8ee4615ed8260302c207 languageName: node linkType: hard @@ -10618,18 +11082,18 @@ __metadata: linkType: hard "ignore-walk@npm:^6.0.0": - version: 6.0.4 - resolution: "ignore-walk@npm:6.0.4" + version: 6.0.5 + resolution: "ignore-walk@npm:6.0.5" dependencies: minimatch: ^9.0.0 - checksum: 8161bb3232eee92367049b186a02ad35e3a47edda2de0c0eb216aa89cf6183c33c46aef22b25e1bf5105c643bd2cc2bb722f474870a93a3c56ef8cca22eb64a1 + checksum: 06f88a53c412385ca7333276149a7e9461b7fad977c44272d854522b0d456c2aa75d832bd3980a530e2c3881126aa9cc4782b3551ca270fffc0ce7c2b4a2e199 languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.3.0 - resolution: "ignore@npm:5.3.0" - checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9 +"ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1": + version: 5.3.1 + resolution: "ignore@npm:5.3.1" + checksum: 71d7bb4c1dbe020f915fd881108cbe85a0db3d636a0ea3ba911393c53946711d13a9b1143c7e70db06d571a5822c0a324a6bcde5c9904e7ca5047f01f1bf8cd3 languageName: node linkType: hard @@ -10717,9 +11181,9 @@ __metadata: linkType: hard "ini@npm:^4.1.0, ini@npm:^4.1.1": - version: 4.1.1 - resolution: "ini@npm:4.1.1" - checksum: 0e5909554074fbc31824fa5415b0f604de4a665514c96a897a77bf77353a7ad4743927321270e9d0610a9d510ccd1f3cd77422f7cc80d8f4542dbce75476fb6d + version: 4.1.3 + resolution: "ini@npm:4.1.3" + checksum: 004b2be42388877c58add606149f1a0c7985c90a0ba5dbf45a4738fdc70b0798d922caecaa54617029626505898ac451ff0537a08b949836b49d3267f66542c9 languageName: node linkType: hard @@ -10771,14 +11235,14 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.5": - version: 1.0.6 - resolution: "internal-slot@npm:1.0.6" +"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" dependencies: - get-intrinsic: ^1.2.2 + es-errors: ^1.3.0 hasown: ^2.0.0 side-channel: ^1.0.4 - checksum: 7872454888047553ce97a3fa1da7cc054a28ec5400a9c2e9f4dbe4fe7c1d041cb8e8301467614b80d4246d50377aad2fb58860b294ed74d6700cc346b6f89549 + checksum: cadc5eea5d7d9bc2342e93aae9f31f04c196afebb11bde97448327049f492cd7081e18623ae71388aac9cd237b692ca3a105be9c68ac39c1dec679d7409e33eb languageName: node linkType: hard @@ -10801,6 +11265,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc + languageName: node + linkType: hard + "ip-regex@npm:^4.1.0": version: 4.3.0 resolution: "ip-regex@npm:4.3.0" @@ -10808,13 +11282,6 @@ __metadata: languageName: node linkType: hard -"ip@npm:^2.0.0": - version: 2.0.0 - resolution: "ip@npm:2.0.0" - checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 - languageName: node - linkType: hard - "ipaddr.js@npm:1.9.1": version: 1.9.1 resolution: "ipaddr.js@npm:1.9.1" @@ -10849,14 +11316,13 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": - version: 3.0.2 - resolution: "is-array-buffer@npm:3.0.2" +"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" dependencies: call-bind: ^1.0.2 - get-intrinsic: ^1.2.0 - is-typed-array: ^1.1.10 - checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 + get-intrinsic: ^1.2.1 + checksum: e4e3e6ef0ff2239e75371d221f74bc3c26a03564a22efb39f6bb02609b598917ddeecef4e8c877df2a25888f247a98198959842a5e73236bc7f22cabdf6351a7 languageName: node linkType: hard @@ -10927,7 +11393,7 @@ __metadata: languageName: node linkType: hard -"is-ci@npm:^3.0.0": +"is-ci@npm:^3.0.1": version: 3.0.1 resolution: "is-ci@npm:3.0.1" dependencies: @@ -10951,8 +11417,17 @@ __metadata: version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: - hasown: ^2.0.0 - checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c + hasown: ^2.0.0 + checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c + languageName: node + linkType: hard + +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: ^1.1.13 + checksum: 4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 languageName: node linkType: hard @@ -11062,17 +11537,17 @@ __metadata: languageName: node linkType: hard -"is-map@npm:^2.0.1, is-map@npm:^2.0.2": - version: 2.0.2 - resolution: "is-map@npm:2.0.2" - checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728 +"is-map@npm:^2.0.2, is-map@npm:^2.0.3": + version: 2.0.3 + resolution: "is-map@npm:2.0.3" + checksum: e6ce5f6380f32b141b3153e6ba9074892bbbbd655e92e7ba5ff195239777e767a976dcd4e22f864accaf30e53ebf961ab1995424aef91af68788f0591b7396cc languageName: node linkType: hard -"is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd languageName: node linkType: hard @@ -11169,19 +11644,19 @@ __metadata: languageName: node linkType: hard -"is-set@npm:^2.0.1, is-set@npm:^2.0.2": - version: 2.0.2 - resolution: "is-set@npm:2.0.2" - checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57 +"is-set@npm:^2.0.2, is-set@npm:^2.0.3": + version: 2.0.3 + resolution: "is-set@npm:2.0.3" + checksum: 36e3f8c44bdbe9496c9689762cc4110f6a6a12b767c5d74c0398176aa2678d4467e3bf07595556f2dba897751bde1422480212b97d973c7b08a343100b0c0dfe languageName: node linkType: hard -"is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + call-bind: ^1.0.7 + checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 languageName: node linkType: hard @@ -11249,12 +11724,12 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": - version: 1.1.12 - resolution: "is-typed-array@npm:1.1.12" +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.3": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" dependencies: - which-typed-array: ^1.1.11 - checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + which-typed-array: ^1.1.14 + checksum: 150f9ada183a61554c91e1c4290086d2c100b0dff45f60b028519be72a8db964da403c48760723bf5253979b8dffe7b544246e0e5351dcd05c5fdb1dcc1dc0f0 languageName: node linkType: hard @@ -11293,10 +11768,10 @@ __metadata: languageName: node linkType: hard -"is-weakmap@npm:^2.0.1": - version: 2.0.1 - resolution: "is-weakmap@npm:2.0.1" - checksum: 1222bb7e90c32bdb949226e66d26cb7bce12e1e28e3e1b40bfa6b390ba3e08192a8664a703dff2a00a84825f4e022f9cd58c4599ff9981ab72b1d69479f4f7f6 +"is-weakmap@npm:^2.0.2": + version: 2.0.2 + resolution: "is-weakmap@npm:2.0.2" + checksum: f36aef758b46990e0d3c37269619c0a08c5b29428c0bb11ecba7f75203442d6c7801239c2f31314bc79199217ef08263787f3837d9e22610ad1da62970d6616d languageName: node linkType: hard @@ -11309,13 +11784,13 @@ __metadata: languageName: node linkType: hard -"is-weakset@npm:^2.0.1": - version: 2.0.2 - resolution: "is-weakset@npm:2.0.2" +"is-weakset@npm:^2.0.3": + version: 2.0.3 + resolution: "is-weakset@npm:2.0.3" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.1 - checksum: 5d8698d1fa599a0635d7ca85be9c26d547b317ed8fd83fc75f03efbe75d50001b5eececb1e9971de85fcde84f69ae6f8346bc92d20d55d46201d328e4c74a367 + call-bind: ^1.0.7 + get-intrinsic: ^1.2.4 + checksum: 8b6a20ee9f844613ff8f10962cfee49d981d584525f2357fee0a04dfbcde9fd607ed60cb6dab626dbcc470018ae6392e1ff74c0c1aced2d487271411ad9d85ae languageName: node linkType: hard @@ -11404,9 +11879,22 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^3.1.2": + version: 3.4.0 + resolution: "jackspeak@npm:3.4.0" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 350f6f311018bb175ffbe736b19c26ac0b134bb5a17a638169e89594eb0c24ab1c658ab3a2fda24ff63b3b19292e1a5ec19d2255bc526df704e8168d392bef85 + languageName: node + linkType: hard + "jake@npm:^10.8.5": - version: 10.8.7 - resolution: "jake@npm:10.8.7" + version: 10.9.1 + resolution: "jake@npm:10.9.1" dependencies: async: ^3.2.3 chalk: ^4.0.2 @@ -11414,7 +11902,7 @@ __metadata: minimatch: ^3.1.2 bin: jake: bin/cli.js - checksum: a23fd2273fb13f0d0d845502d02c791fd55ef5c6a2d207df72f72d8e1eac6d2b8ffa6caf660bc8006b3242e0daaa88a3ecc600194d72b5c6016ad56e9cd43553 + checksum: 49659c156b8ad921af377fb782505ae3cc7e7dd8793695b782070d99b4b66d2688b4e3efb32e09252400bfe6e49a7fb393a3a0959e8e1a51dbda95bcacbb9c36 languageName: node linkType: hard @@ -11433,22 +11921,22 @@ __metadata: linkType: hard "joi@npm:^17.6.0": - version: 17.11.0 - resolution: "joi@npm:17.11.0" + version: 17.13.1 + resolution: "joi@npm:17.13.1" dependencies: - "@hapi/hoek": ^9.0.0 - "@hapi/topo": ^5.0.0 - "@sideway/address": ^4.1.3 + "@hapi/hoek": ^9.3.0 + "@hapi/topo": ^5.1.0 + "@sideway/address": ^4.1.5 "@sideway/formula": ^3.0.1 "@sideway/pinpoint": ^2.0.0 - checksum: 3a4e9ecba345cdafe585e7ed8270a44b39718e11dff3749aa27e0001a63d578b75100c062be28e6f48f960b594864034e7a13833f33fbd7ad56d5ce6b617f9bf + checksum: e755140446a0e0fb679c0f512d20dfe1625691de368abe8069507c9bccae5216b5bb56b5a83100a600808b1753ab44fdfdc9933026268417f84b6e0832a9604e languageName: node linkType: hard "jose@npm:^4.14.6": - version: 4.15.4 - resolution: "jose@npm:4.15.4" - checksum: dccad91cb3357f36423774a0b89ad830dd84b31090de65cd139b85488439f16a00f8c59c0773825e8a1adb0dd9d13ad725ad66e6ea33880ecb3959bb99e1ea5b + version: 4.15.7 + resolution: "jose@npm:4.15.7" + checksum: 8336d650eebc9ab4904dd1a4a4abf4ea7f0e8daa43cb83b4dbd5b027aadb1dbc3e6684009e10d30acc1897e83fb38bfca22526bec8efa9923fd38b2122cc5bae languageName: node linkType: hard @@ -11460,18 +11948,19 @@ __metadata: linkType: hard "js-beautify@npm:^1.6.14": - version: 1.14.11 - resolution: "js-beautify@npm:1.14.11" + version: 1.15.1 + resolution: "js-beautify@npm:1.15.1" dependencies: config-chain: ^1.1.13 - editorconfig: ^1.0.3 + editorconfig: ^1.0.4 glob: ^10.3.3 + js-cookie: ^3.0.5 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 + checksum: 0428ea358cdf169da15e11a8b63f13845ee39c707f3718a3ec515eb89d585544525aa8ba5306503431c61e33e1fbfebdf2af41c461e512619d8a2f8664d6c0c4 languageName: node linkType: hard @@ -11482,6 +11971,13 @@ __metadata: languageName: node linkType: hard +"js-cookie@npm:^3.0.5": + version: 3.0.5 + resolution: "js-cookie@npm:3.0.5" + checksum: 2dbd2809c6180fbcf060c6957cb82dbb47edae0ead6bd71cbeedf448aa6b6923115003b995f7d3e3077bfe2cb76295ea6b584eb7196cca8ba0a09f389f64967a + languageName: node + linkType: hard + "js-sha3@npm:0.8.0": version: 0.8.0 resolution: "js-sha3@npm:0.8.0" @@ -11496,10 +11992,10 @@ __metadata: languageName: node linkType: hard -"js-tokens@npm:^8.0.2": - version: 8.0.3 - resolution: "js-tokens@npm:8.0.3" - checksum: b749c808290ec1932fdf5486412074c64da6f48387a89d58f00e84058db89a7707f62d2a066fd673030dd6776bf656b50f6e0fa34135f9b3cacccde39a508977 +"js-tokens@npm:^9.0.0": + version: 9.0.0 + resolution: "js-tokens@npm:9.0.0" + checksum: 427d0db681caab0c906cfc78a0235bbe7b41712cee83f3f14785c1de079a1b1a85693cc8f99a3f71685d0d76acaa5b9c8920850b67f93d3eeb7ef186987d186c languageName: node linkType: hard @@ -11514,6 +12010,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + "jsbn@npm:~0.1.0": version: 0.1.1 resolution: "jsbn@npm:0.1.1" @@ -11522,10 +12025,11 @@ __metadata: linkType: hard "jsdom@npm:^23.0.0": - version: 23.0.1 - resolution: "jsdom@npm:23.0.1" + version: 23.2.0 + resolution: "jsdom@npm:23.2.0" dependencies: - cssstyle: ^3.0.0 + "@asamuzakjp/dom-selector": ^2.0.1 + cssstyle: ^4.0.1 data-urls: ^5.0.0 decimal.js: ^10.4.3 form-data: ^4.0.0 @@ -11533,7 +12037,6 @@ __metadata: http-proxy-agent: ^7.0.0 https-proxy-agent: ^7.0.2 is-potential-custom-element-name: ^1.0.1 - nwsapi: ^2.2.7 parse5: ^7.1.2 rrweb-cssom: ^0.6.0 saxes: ^6.0.0 @@ -11544,14 +12047,23 @@ __metadata: whatwg-encoding: ^3.1.1 whatwg-mimetype: ^4.0.0 whatwg-url: ^14.0.0 - ws: ^8.14.2 + ws: ^8.16.0 xml-name-validator: ^5.0.0 peerDependencies: canvas: ^2.11.2 peerDependenciesMeta: canvas: optional: true - checksum: 1f4f21549bf3cb787521adb466dcba269187109a84ea5ad42446b5fc11336c4a303670dc51b742b1692e75ca76f41a9d8fc72e8fc2f7cb53e372441e6e3ce1dd + checksum: 3ba97e6ac56c38d92d0ce2d0fac5de4042f7dec40d127872e1aa88dd379980f8ea2108a008319ceac54dc07a784078ed4b4401bf9109a76276ca2cace229c8df + languageName: node + linkType: hard + +"jsesc@npm:^2.5.1": + version: 2.5.2 + resolution: "jsesc@npm:2.5.2" + bin: + jsesc: bin/jsesc + checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d languageName: node linkType: hard @@ -11576,10 +12088,10 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.1 - resolution: "json-parse-even-better-errors@npm:3.0.1" - checksum: bf74fa3f715e56699ccd68b80a7d20908de432a3fae2d5aa2ed530a148e9d9ccdf8e6983b93d9966a553aa70dcf003ce3a7ffec2c0ce74d2a6173e3691a426f0 +"json-parse-even-better-errors@npm:^3.0.0, json-parse-even-better-errors@npm:^3.0.1": + version: 3.0.2 + resolution: "json-parse-even-better-errors@npm:3.0.2" + checksum: 6f04ea6c9ccb783630a59297959247e921cc90b917b8351197ca7fd058fccc7079268fd9362be21ba876fc26aa5039369dd0a2280aae49aae425784794a94927 languageName: node linkType: hard @@ -11617,7 +12129,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 @@ -11665,13 +12177,6 @@ __metadata: languageName: node linkType: hard -"jsonc-parser@npm:^3.2.0": - version: 3.2.0 - resolution: "jsonc-parser@npm:3.2.0" - checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 - languageName: node - linkType: hard - "jsonfile@npm:^6.0.1": version: 6.1.0 resolution: "jsonfile@npm:6.1.0" @@ -11746,9 +12251,9 @@ __metadata: languageName: node linkType: hard -"juice@npm:^9.0.0": - version: 9.1.0 - resolution: "juice@npm:9.1.0" +"juice@npm:^10.0.0": + version: 10.0.0 + resolution: "juice@npm:10.0.0" dependencies: cheerio: ^1.0.0-rc.12 commander: ^6.1.0 @@ -11757,7 +12262,7 @@ __metadata: web-resource-inliner: ^6.0.1 bin: juice: bin/juice - checksum: 95f20fa183baa17360d7f03f2699f7cbc3476fb2e3a2d1d81d28f2ce1e5cd61a634a05cad26cfe83174c730ecbde18d8db9bc244b915741833fa6ce1c61c6864 + checksum: 83fd686028896b565247dd29169e26d0bdf729f762d815e5b75edca714e105ee223a51d095f1c33220c4f91ce5f1da7a10e74b31483de4dfb77e411a8b672a09 languageName: node linkType: hard @@ -11796,13 +12301,6 @@ __metadata: languageName: node linkType: hard -"kareem@npm:2.3.2": - version: 2.3.2 - resolution: "kareem@npm:2.3.2" - checksum: 61ee3adb273e3e999eae731119bd74e40fd01ffef585b4e47756ca29dfc939a03c6a1dd8a43f2a864e599c3716e00404d1812e685b32ec7f9c52d6cedf2f2fcb - languageName: node - linkType: hard - "katex@npm:^0.13.18": version: 0.13.24 resolution: "katex@npm:0.13.24" @@ -11838,9 +12336,9 @@ __metadata: linkType: hard "language-subtag-registry@npm:^0.3.20": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a + version: 0.3.23 + resolution: "language-subtag-registry@npm:0.3.23" + checksum: 0b64c1a6c5431c8df648a6d25594ff280613c886f4a1a542d9b864e5472fb93e5c7856b9c41595c38fac31370328fc79fcc521712e89ea6d6866cbb8e0995d81 languageName: node linkType: hard @@ -11871,18 +12369,18 @@ __metadata: linkType: hard "libnpmaccess@npm:^7.0.2": - version: 7.0.2 - resolution: "libnpmaccess@npm:7.0.2" + version: 7.0.3 + resolution: "libnpmaccess@npm:7.0.3" dependencies: npm-package-arg: ^10.1.0 npm-registry-fetch: ^14.0.3 - checksum: 73d49f39391173276c46c12e32f503709338efd867d255d062ae9bc9e9f464d61240747f42bdd6dc6003a5dc275a27352ebfc11ed4cb424091463f302d823f23 + checksum: 8dc0014d0d37a92e13746697993a054daf9860bad224399c33bb30523fdfa84f7d0ef94b21f3a830b5a6bffd33315e2a6ded8fc7268ca37ab971356e4c92bf86 languageName: node linkType: hard "libnpmdiff@npm:^5.0.20": - version: 5.0.20 - resolution: "libnpmdiff@npm:5.0.20" + version: 5.0.21 + resolution: "libnpmdiff@npm:5.0.21" dependencies: "@npmcli/arborist": ^6.5.0 "@npmcli/disparity-colors": ^3.0.0 @@ -11893,17 +12391,17 @@ __metadata: npm-package-arg: ^10.1.0 pacote: ^15.0.8 tar: ^6.1.13 - checksum: 7c26de78925f7e31b4c9644c00f1d4befbbc0fb6e44cb62868925cfd39ecc31b4a8f27314e694c5447808c47a305e352ed544ea7b205a460e8fae599a82e7313 + checksum: 6c554fb3efdebc7b3554c4d81252c6165ccfd4fc7e09aa73a69136d2142d17c803123f723d2ac0f4d0396504ff306be3cf7c12dbada150291947de1a3febcb7a languageName: node linkType: hard "libnpmexec@npm:^6.0.4": - version: 6.0.4 - resolution: "libnpmexec@npm:6.0.4" + version: 6.0.5 + resolution: "libnpmexec@npm:6.0.5" dependencies: "@npmcli/arborist": ^6.5.0 "@npmcli/run-script": ^6.0.0 - ci-info: ^3.7.1 + ci-info: ^4.0.0 npm-package-arg: ^10.1.0 npmlog: ^7.0.1 pacote: ^15.0.8 @@ -11912,56 +12410,56 @@ __metadata: read-package-json-fast: ^3.0.2 semver: ^7.3.7 walk-up-path: ^3.0.1 - checksum: 3b34975737b312aec3130ca5d78ee33da60586411d9ccf04ed44fe78573cf824b64fcbe56832254b901b8accf12d43ac7518896c9d9d27f436cb33b9562f0a56 + checksum: a12647df672fb285bbbbfcf5522f864a4646c306925c3228cfc941366d0eb865359895eb8e4f93e3c815009c2e68d30658c360cf5b0c5eeb479c985ae473cc95 languageName: node linkType: hard "libnpmfund@npm:^4.2.1": - version: 4.2.1 - resolution: "libnpmfund@npm:4.2.1" + version: 4.2.2 + resolution: "libnpmfund@npm:4.2.2" dependencies: "@npmcli/arborist": ^6.5.0 - checksum: 8099266c3f37431c42f4285e4c3a22a82c0d66d0c1e536a5732672008592609d2c053c451f66934c437301924419bc519b098d0eaa82cdf6a8861f5fb375a71c + checksum: 3a33d0b411b4c9493aa12968187ac12f81e04f8477e6e8586dac6bbc535450e9db10861852a2b1f545803ae1ff2b042779209a649830b5e5ca7ec8029c3221f6 languageName: node linkType: hard "libnpmhook@npm:^9.0.3": - version: 9.0.3 - resolution: "libnpmhook@npm:9.0.3" + version: 9.0.4 + resolution: "libnpmhook@npm:9.0.4" dependencies: aproba: ^2.0.0 npm-registry-fetch: ^14.0.3 - checksum: 535ecefa225eabc466737cfebbba5f7d60745b7ef2845c5e3f7d717ac5ad4e2a9a1bf8aaa73f3ea36bfd044f8ea03783e75e239f34086070d2ce49ddf87b251d + checksum: 8f4c6cebda3b6c3d01f9aa71bcfc2d3bf10dceae65fc201e8c5cd776eb16468aec3456f65887dd306ce9f3ffa4b733c4140363411dbea367b1fff1d2015f4174 languageName: node linkType: hard "libnpmorg@npm:^5.0.4": - version: 5.0.4 - resolution: "libnpmorg@npm:5.0.4" + version: 5.0.5 + resolution: "libnpmorg@npm:5.0.5" dependencies: aproba: ^2.0.0 npm-registry-fetch: ^14.0.3 - checksum: 4e170ba145f74f75106ecfa549f8aea3fbd88806f0f24d329d68d7198a3f9bceca2008accaf2272f2bad5f32f7543f66d12afc4ad01076669de11efbcd5e2316 + checksum: e2cd9630ecf1df18bc5a8aec0265cef0897cb79d20f3ba190b60d166b6c8ba8c253e76436918d3fd4ca7c4da3b2c9507071349ad67f32254b9e6fcc30f25890a languageName: node linkType: hard "libnpmpack@npm:^5.0.20": - version: 5.0.20 - resolution: "libnpmpack@npm:5.0.20" + version: 5.0.21 + resolution: "libnpmpack@npm:5.0.21" dependencies: "@npmcli/arborist": ^6.5.0 "@npmcli/run-script": ^6.0.0 npm-package-arg: ^10.1.0 pacote: ^15.0.8 - checksum: 5cea162805b604089d3064e9a9a8b74972273c9b95d23b0bcca957a0b1e255506e35e890ccb6775a4035487e8600eb2be859605a5846a50d60c1b95a0e311157 + checksum: d63fd888448638a10ca3064b221e3d761e82600b5cdf99096dbf78dc0936fd2e333981ddef8c7bb1583282017289667f25444b627fa299921a892ccea14bc437 languageName: node linkType: hard "libnpmpublish@npm:^7.5.1": - version: 7.5.1 - resolution: "libnpmpublish@npm:7.5.1" + version: 7.5.2 + resolution: "libnpmpublish@npm:7.5.2" dependencies: - ci-info: ^3.6.1 + ci-info: ^4.0.0 normalize-package-data: ^5.0.0 npm-package-arg: ^10.1.0 npm-registry-fetch: ^14.0.3 @@ -11969,39 +12467,39 @@ __metadata: semver: ^7.3.7 sigstore: ^1.4.0 ssri: ^10.0.1 - checksum: 951f151744a5aea89c01bcd37f161d8bf5db29ef77d8e4dd78fb2afc16a0901907785d12a65a5e1e520ed6660bd6498d97bc933cfd1b5f7d924d412852390c0a + checksum: aad54f59a7bba55370be58a4d7c4488b79bc164a3abf84c5ab5d4c258eb76daee68d97b8f202550f81e8b5f830143094d7153490a51a7653c719da66d35a3292 languageName: node linkType: hard "libnpmsearch@npm:^6.0.2": - version: 6.0.2 - resolution: "libnpmsearch@npm:6.0.2" + version: 6.0.3 + resolution: "libnpmsearch@npm:6.0.3" dependencies: npm-registry-fetch: ^14.0.3 - checksum: 7a62e5cb1ce7c92eb62fc41070a4591684b8a1c8e6becdd909ed929d047d1ac9226bb4818b1919a295d8d59d8836431eb477064c0f37420d4d8d571849a49316 + checksum: afb9ac97eb2b33e37dbf802ea06769c81ef50574b20e538fb58c73d6f0962fd97a122b0931b600bb01de12c0217d62dbab93db750f8ab876f51feaa71586e30a languageName: node linkType: hard "libnpmteam@npm:^5.0.3": - version: 5.0.3 - resolution: "libnpmteam@npm:5.0.3" + version: 5.0.4 + resolution: "libnpmteam@npm:5.0.4" dependencies: aproba: ^2.0.0 npm-registry-fetch: ^14.0.3 - checksum: a39ccdb4a6c946ee7345e5913ea4ff86c645ecd1f7809965caaa465f6d0116224cc17fda4ddccebf564906bbc24d7c20b677417fc600327013f5d57c0c273e64 + checksum: 9120d425460a743b4febc01191aed75cb675648c483df1322426065d7699b46beb23f7672dfbc13e797320fe1930fe644b30185c1d711964184f7ac028d8c72b languageName: node linkType: hard "libnpmversion@npm:^4.0.2": - version: 4.0.2 - resolution: "libnpmversion@npm:4.0.2" + version: 4.0.3 + resolution: "libnpmversion@npm:4.0.3" dependencies: "@npmcli/git": ^4.0.1 "@npmcli/run-script": ^6.0.0 json-parse-even-better-errors: ^3.0.0 proc-log: ^3.0.0 semver: ^7.3.7 - checksum: 4666db467132df0ed893eee04729ba2c50562e32a9e33eaab0f051fab6e4297c2423a823e862f9af51c5c71f01d563b07dc96b3dab7a2004587739d04787e740 + checksum: 0833570c5b38f8bd06482eb04a59fe3f01806365469446a3cccdf28cd6f42cda768e957a2d48bb26fd7f0902e100b858c2099c6cd7b1c6cc9dea278555f5d23d languageName: node linkType: hard @@ -12015,13 +12513,13 @@ __metadata: linkType: hard "light-my-request@npm:^5.11.0": - version: 5.11.0 - resolution: "light-my-request@npm:5.11.0" + version: 5.13.0 + resolution: "light-my-request@npm:5.13.0" dependencies: - cookie: ^0.5.0 - process-warning: ^2.0.0 + cookie: ^0.6.0 + process-warning: ^3.0.0 set-cookie-parser: ^2.4.1 - checksum: f639edb4664534bfcc87aff3fc36e7199ef5b04c399ce51a87481786d23ad1d439a71a5beeada5d0fe607c9d6efccbcd1bef265f31397e130f4077d43cc6d45f + checksum: d0264c43813d4c9e3802d8292821ccee214ec793ce8b9b8f7433d005de1a220483782c64eb83494c2307e2b4e3eb3ca506f6eebd087ec022b43f770e1826f2d8 languageName: node linkType: hard @@ -12040,9 +12538,9 @@ __metadata: linkType: hard "lilconfig@npm:^3.0.0": - version: 3.0.0 - resolution: "lilconfig@npm:3.0.0" - checksum: a155f1cd24d324ab20dd6974db9ebcf3fb6f2b60175f7c052d917ff8a746b590bc1ee550f6fc3cb1e8716c8b58304e22fe2193febebc0cf16fa86d85e6f896c5 + version: 3.1.2 + resolution: "lilconfig@npm:3.1.2" + checksum: 4e8b83ddd1d0ad722600994e6ba5d858ddca14f0587aa6b9c8185e17548149b5e13d4d583d811e9e9323157fa8c6a527e827739794c7502b59243c58e210b8c3 languageName: node linkType: hard @@ -12466,10 +12964,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.1.0 - resolution: "lru-cache@npm:10.1.0" - checksum: 58056d33e2500fbedce92f8c542e7c11b50d7d086578f14b7074d8c241422004af0718e08a6eaae8705cee09c77e39a61c1c79e9370ba689b7010c152e6a76ab +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 98e8fc93691c546f719a76103ef2bee5a3ac823955c755a47641ec41f8c7fafa1baeaba466937cc1cbfa9cfd47e03536d10e2db3158a64ad91ff3a58a32c893e languageName: node linkType: hard @@ -12541,11 +13039,11 @@ __metadata: linkType: hard "magic-string@npm:^0.30.5": - version: 0.30.8 - resolution: "magic-string@npm:0.30.8" + version: 0.30.10 + resolution: "magic-string@npm:0.30.10" dependencies: "@jridgewell/sourcemap-codec": ^1.4.15 - checksum: 79922f4500d3932bb587a04440d98d040170decf432edc0f91c0bf8d41db16d364189bf800e334170ac740918feda62cd39dcc170c337dc18050cfcf00a5f232 + checksum: 456fd47c39b296c47dff967e1965121ace35417eab7f45a99e681e725b8661b48e1573c366ee67a27715025b3740773c46b088f115421c7365ea4ea6fa10d399 languageName: node linkType: hard @@ -12618,8 +13116,8 @@ __metadata: linkType: hard "make-fetch-happen@npm:^13.0.0": - version: 13.0.0 - resolution: "make-fetch-happen@npm:13.0.0" + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" dependencies: "@npmcli/agent": ^2.0.0 cacache: ^18.0.0 @@ -12630,9 +13128,10 @@ __metadata: minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 negotiator: ^0.6.3 + proc-log: ^4.2.0 promise-retry: ^2.0.1 ssri: ^10.0.0 - checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af + checksum: 5c9fad695579b79488fa100da05777213dd9365222f85e4757630f8dd2a21a79ddd3206c78cfd6f9b37346819681782b67900ac847a57cf04190f52dda5343fd languageName: node linkType: hard @@ -12739,12 +13238,12 @@ __metadata: linkType: hard "match-sorter@npm:^6.0.2, match-sorter@npm:^6.3.1": - version: 6.3.1 - resolution: "match-sorter@npm:6.3.1" + version: 6.3.4 + resolution: "match-sorter@npm:6.3.4" dependencies: - "@babel/runtime": ^7.12.5 - remove-accents: 0.4.2 - checksum: a4b02b676ac4ce64a89a091539ee4a70a802684713bcf06f2b70787927f510fe8a2adc849f9288857a90906083ad303467e530e8723b4a9756df9994fc164550 + "@babel/runtime": ^7.23.8 + remove-accents: 0.5.0 + checksum: 950c1600173a639e216947559a389b64258d52f33aea3a6ddb97500589888b83c976a028f731f40bc08d9d8af20de7916992fabb403f38330183a1df44c7634b languageName: node linkType: hard @@ -12852,6 +13351,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.0.30": + version: 2.0.30 + resolution: "mdn-data@npm:2.0.30" + checksum: d6ac5ac7439a1607df44b22738ecf83f48e66a0874e4482d6424a61c52da5cde5750f1d1229b6f5fa1b80a492be89465390da685b11f97d62b8adcc6e88189aa + languageName: node + linkType: hard + "mdurl@npm:^1.0.1": version: 1.0.1 resolution: "mdurl@npm:1.0.1" @@ -12884,18 +13390,18 @@ __metadata: linkType: hard "memoizee@npm:^0.4.15": - version: 0.4.15 - resolution: "memoizee@npm:0.4.15" + version: 0.4.17 + resolution: "memoizee@npm:0.4.17" dependencies: - d: ^1.0.1 - es5-ext: ^0.10.53 + d: ^1.0.2 + es5-ext: ^0.10.64 es6-weak-map: ^2.0.3 event-emitter: ^0.3.5 is-promise: ^2.2.2 lru-queue: ^0.1.0 next-tick: ^1.1.0 timers-ext: ^0.1.7 - checksum: 4065d94416dbadac56edf5947bf342beca0e9f051f33ad60d7c4baf3f6ca0f3c6fdb770c5caed5a89c0ceaf9121428582f396445d591785281383d60aa883418 + checksum: 9f2fa3f55d3b053ddfb7f2ce47ea3f51aa88d4425fa3aee0daf48bd41ecb8f1787b2150b14bcf745d8c4be8e2c07da614d857e11f79a6951420bbb0029b05a9c languageName: node linkType: hard @@ -12974,14 +13480,14 @@ __metadata: linkType: hard "merge-refs@npm:^1.0.0": - version: 1.2.2 - resolution: "merge-refs@npm:1.2.2" + version: 1.3.0 + resolution: "merge-refs@npm:1.3.0" peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 26f34397adb4c1dbef150c3049ed3800e6d37937f1138b048a8d61d8a85ca5b54c8c9245b6d67118dbbd795af4228789eeb87a2eac9905b8a869bfd1785df005 + checksum: 8400f716a77857dac6b5d49cd5ef69cec7bff6c5555785c5e91a5142fbb5f3e6fe81282bc5be1f01c0c0843ed29f5b4169bfa9838ec69c459b4538f3fef3e79c languageName: node linkType: hard @@ -13083,7 +13589,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:4.0.5, micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": +"micromatch@npm:4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" dependencies: @@ -13093,6 +13599,16 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": + version: 4.0.7 + resolution: "micromatch@npm:4.0.7" + dependencies: + braces: ^3.0.3 + picomatch: ^2.3.1 + checksum: 3cde047d70ad80cf60c787b77198d680db3b8c25b23feb01de5e2652205d9c19f43bd81882f69a0fd1f0cde6a7a122d774998aad3271ddb1b8accf8a0f480cf7 + languageName: node + linkType: hard + "microseconds@npm:0.2.0": version: 0.2.0 resolution: "microseconds@npm:0.2.0" @@ -13163,11 +13679,11 @@ __metadata: linkType: hard "mime@npm:^4.0.0": - version: 4.0.1 - resolution: "mime@npm:4.0.1" + version: 4.0.3 + resolution: "mime@npm:4.0.3" bin: mime: bin/cli.js - checksum: a931283bc31570cc9c63fbad24fdf178b4dd545462f93543eff634b24d2b65064585eb347cdf0720316bfa5ca0943115694672f2bc4895f8e2366d280ad481f2 + checksum: 17f7bf9f566f0127fac3b93acd5dd37fcfa7cce5842b9fe599fdf7a716cbc3d8b69aac0e8a1a5df834d44a610a51d04eea6e38d2dbc2f1a2326e9a759a5821dc languageName: node linkType: hard @@ -13238,7 +13754,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.3, minimatch@npm:^9.0.0, minimatch@npm:^9.0.1, minimatch@npm:^9.0.3": +"minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -13256,6 +13772,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.1, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: ^2.0.1 + checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 + languageName: node + linkType: hard + "minimist-options@npm:4.1.0": version: 4.1.0 resolution: "minimist-options@npm:4.1.0" @@ -13308,8 +13833,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" dependencies: encoding: ^0.1.13 minipass: ^7.0.3 @@ -13318,7 +13843,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a + checksum: 8047d273236157aab27ab7cd8eab7ea79e6ecd63e8f80c3366ec076cb9a0fed550a6935bab51764369027c414647fd8256c2a20c5445fb250c483de43350de83 languageName: node linkType: hard @@ -13375,10 +13900,10 @@ __metadata: 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 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 languageName: node linkType: hard @@ -13392,405 +13917,406 @@ __metadata: languageName: node linkType: hard -"mjml-accordion@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-accordion@npm:4.14.1" +"mjml-accordion@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-accordion@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 66212dcf89531da230115c786dec24194d8ec9a4c93bcc1cfdbac332be07678eee3b8479d46f155cb60bf13358edd5cd7e4d6538ad5f9a910cbee5bb6b450855 + mjml-core: 4.15.3 + checksum: 3fa1ffe1624e5b51b8e21f6321043746be9264752de8ae635203297797fde38e9ea8e47db7228c62c22f7ad764410951868253246b05926db9caeb9e7bf3e1a8 languageName: node linkType: hard -"mjml-body@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-body@npm:4.14.1" +"mjml-body@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-body@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 27388e15681bb25412a7123ae82559e6cb5586293aef3aa2cf57138bee401c1b53e84d8efacef2c9db4cb7bf8dc8cac741b7907ec11036f2b804178db511301c + mjml-core: 4.15.3 + checksum: 744ef4cf1a0acc8e326019f6d5b098ba068ba7d3a85f9991d94f7ea24e99497ecd6a3234732a3b8969a8a1939f3bfc8ee6189c782d5b1ebd48668d0d37680926 languageName: node linkType: hard -"mjml-button@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-button@npm:4.14.1" +"mjml-button@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-button@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 55fa3228476fbb17c51d63fbc9a18ce280c3246a69164bbd6d93f4670b3a9f93e985cece5958cc94ff0b60fbc199bd1382fd85d27aac0677517926ec8dd0ad6f + mjml-core: 4.15.3 + checksum: 7866387019ae664badf79ba8f51ad05aaabbfd5f06b02d01de933564bbdad6d960d9b50677270e14fda0c3fd8c7ffd723cab27bbd41219ebb2b712d5a593c5ac languageName: node linkType: hard -"mjml-carousel@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-carousel@npm:4.14.1" +"mjml-carousel@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-carousel@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: db6d7847722ef1d4fd2b74aba04853156c729ba1a99e5565fbe5c32ed96733de1846fc41995505ec950de4953fa415586251c1e65f731725edd9d4b08b259e87 + mjml-core: 4.15.3 + checksum: e750069002a918d6e98d2a39d615d26db8d24514625df2b1432091b483eb8f0b31347bb89a68b3b7d9b47fd0b7f5c91cc8d00d7ca1e168c5e2c7e7129452208b languageName: node linkType: hard -"mjml-cli@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-cli@npm:4.14.1" +"mjml-cli@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-cli@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 chokidar: ^3.0.0 - glob: ^7.1.1 + glob: ^10.3.10 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 + minimatch: ^9.0.3 + mjml-core: 4.15.3 + mjml-migrate: 4.15.3 + mjml-parser-xml: 4.15.3 + mjml-validator: 4.15.3 + yargs: ^17.7.2 bin: mjml-cli: bin/mjml - checksum: ed3a08c68b6c5261e173674d1f1276b2cd636f2edc8713234a071befe919f9f9aa22e254480516d4b8d49eef22989017ce4327418c1c03fe08b004b6d1f8d136 + checksum: f02b2f6047f5c81888a17c6681c70f4c6e5212c59b981ef7615a5a55630e610e9688175c125f6a5b31fe9cc781c11f925226ad2b6c53a759b7b3dade51e0b6bd languageName: node linkType: hard -"mjml-column@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-column@npm:4.14.1" +"mjml-column@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-column@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: a8eb4f321b9015ba8be96d08019502ada557fe3ba55413abf71b39a9ce209d0a3550ba03714a91b03b065af8b64582f6b3703b249f77c12bc1b54a499ac10ee2 + mjml-core: 4.15.3 + checksum: b3fb8640739c6dbbd53b5306224c351fc23eed60864fe2777b28fb39a2a43cc7db3c7b44c929b9e9f420f0142dd978f1fdc097cf3c91696a849fd565a5f7056c languageName: node linkType: hard -"mjml-core@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-core@npm:4.14.1" +"mjml-core@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-core@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 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 + juice: ^10.0.0 lodash: ^4.17.21 - mjml-migrate: 4.14.1 - mjml-parser-xml: 4.14.1 - mjml-validator: 4.13.0 - checksum: fe46769b1746b1da90ddd39c584a6c8f7db80e125e079ce83cfd8ab4888e5abfff2933f573993926b36721de194b261c28f078b9316c395b185fd4098298c025 + mjml-migrate: 4.15.3 + mjml-parser-xml: 4.15.3 + mjml-validator: 4.15.3 + checksum: fa5d5ce6b92fd10254afd134c68656c3c6b9f413a14e0e2ee4625078abcdfbbcce2b4864c98f417f20841d783aa38e66d2ae101017bfb84bbcfca3c65dfd17a3 languageName: node linkType: hard -"mjml-divider@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-divider@npm:4.14.1" +"mjml-divider@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-divider@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: b44fab9de9751caf626ca6206b58c2a9ac7788c54c56d91cc892f77ed164a0fd2021422ef1019adb147a145873db499bb89f1518aa4326face1135acd8f61294 + mjml-core: 4.15.3 + checksum: b994ee2e7b2812360ea23c794fcb86dc6c1f3f529cf2ab13a5353bfed718ad16371dfbf63bad8ffa132ba3ada8df05bef30dc4c9a9d566429ce947c7ab63baf9 languageName: node linkType: hard -"mjml-group@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-group@npm:4.14.1" +"mjml-group@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-group@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 17cec7be9544ae32121cac12cf6dffd0a234bb2c14e2e72df230c52f1834f34fbd2df6ed15661491d0eee2c95dd7ad77e6048ca0ca012c9970d96bcfe8a4e77e + mjml-core: 4.15.3 + checksum: fe780123bdf091323ec6648f5d41ff5b87e9f033d695b41ec952810c58ba32d838248c4333f373648f7b888e7d462ac266913511ad2763df37492a3da281dd4e languageName: node linkType: hard -"mjml-head-attributes@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-attributes@npm:4.14.1" +"mjml-head-attributes@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-attributes@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 93783e5ce4df95c745fee65cf2a4787eadbd548bb2d35f4c408d50cd4f81652061da4fcf54b4861db40bef115b60bb29f36faf6478033ad32e5e467415ec394a + mjml-core: 4.15.3 + checksum: b9c58443237c90c588b2ad8b1d72f5ac207d8eed7473bf8dcc82508cbe20a9738e6c3921f47cf89a73a3e388b85ddab093e366f9c258311235d3125a80466352 languageName: node linkType: hard -"mjml-head-breakpoint@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-breakpoint@npm:4.14.1" +"mjml-head-breakpoint@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-breakpoint@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: b52ea526f9291e0919ec82a7cc89e1e4d5a22c78280bc039b97648a3b938778d3bc7ff77b658a8a5d247c80327d2677f1591a5638039edc0d7c6f86670a1aeec + mjml-core: 4.15.3 + checksum: bf348f65f3faa2cdd9be7f8f889af5ccb52f620c6f00bb86f08bd54e72e0e7573ad9c49bafa944f85c7140481e48d531e0e314ab7ff9327f44ab1adff297feea languageName: node linkType: hard -"mjml-head-font@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-font@npm:4.14.1" +"mjml-head-font@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-font@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 3787977d042634ed338eb5d1be8612494a55419f568187c40517d3c53d57a93d3efd13c82c89d4a5b5c6456082bee12b6f682ededbc24a071600c9986a88ee94 + mjml-core: 4.15.3 + checksum: 32a8ab7787ca6f9b57753f4181b5226f508c9299ca5a7f8a304a90b4540ffa50cd026578b57938b261f2fb90676ad6e633a03e26922d6cc962306c32ae9bc8d9 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" +"mjml-head-html-attributes@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-html-attributes@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: a076f05954e09d7d8d721dc6931a1ecfcfa59126d4c7859c6278404d8e036b83f8eb72fd4285f367324d170bde7df64385ddf093b9f47cf5115fffd85756a510 + mjml-core: 4.15.3 + checksum: 5521c4851894fcbfd1a6b9995637313bf52e26909c9e72a770bd98f913d9432f45cfda3e59c164dc57c5a01702bb0aefffaa44cc31e57bf1a220c0928cbf1a51 languageName: node linkType: hard -"mjml-head-preview@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-preview@npm:4.14.1" +"mjml-head-preview@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-preview@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 9d8301458a93794695a1c50a16dbdd7914c008f0a89ee87be9d83f494966fb0aa51434549a6f183a014e34bfdc23795607bc33a33a1a4225882c8d0208fa3898 + mjml-core: 4.15.3 + checksum: 3d9c1dd0bab3ca836190d6c0dd9f36343a1d4e74da185c0acd83f03eb146c4d3c28aabdd83d963c5cdadf4658d13770eb6be0047e553b09573743c8026817ab8 languageName: node linkType: hard -"mjml-head-style@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-style@npm:4.14.1" +"mjml-head-style@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-style@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 2e96180bd72656c70507f21a37f8cf3c0dc41709052af42e1161d77551df762f62d863635c18dff6d092bab9bd8c8c631c0a09b3c6dc25575f0693ee6627b7ba + mjml-core: 4.15.3 + checksum: b67642cd221ce2dd48ca6983aa5fbdfbe6de868e973c2a522468f1c6acab22a5a3740b30f457288c74d497430626b9b8460a6784c270a0471ca4dec973c11d45 languageName: node linkType: hard -"mjml-head-title@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head-title@npm:4.14.1" +"mjml-head-title@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head-title@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 65dfe9cb5115a9cfe76851b9e5aabaaa30131e55a4346e9ec04bde3234897ffe1ab3e7bb37a695af44deffe4a869dee34668a3d87396ed50b923310fb9baebcd + mjml-core: 4.15.3 + checksum: 99b8de5a861fca8394e1a961826fb7680df66797f18dc2dba6d794871ef331d0122b0ef5b4da45456d3efdcd529e5670658298462a4f4d7b486f216b1199ade3 languageName: node linkType: hard -"mjml-head@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-head@npm:4.14.1" +"mjml-head@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-head@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: c83c930badb7ad0ee5771b13928d2c371aa9b70777393e32361fa356b534d1b282f5698e41dee8f947c687d28580e80b74bac2d3308970884e58152edc86bafd + mjml-core: 4.15.3 + checksum: 205dc76f1fd00a379aabfb9d8267d5e80615d6b403a13d4047346d47d9269ed64972c8d6e21f1bc0727da1271328795f6fbddcdfdaedae85c39514e845b14b04 languageName: node linkType: hard -"mjml-hero@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-hero@npm:4.14.1" +"mjml-hero@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-hero@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 6c6ec8e5168709f09175d030c2a6fc7326f7a2e076cf09c0676e78bd941521e2c4295335bfdce8b5c31ea946a1925edcb780aced73b0dbfda40c07a463526c93 + mjml-core: 4.15.3 + checksum: 726c216d4c34440c97b6893e0836e3fc14376f159a4645807b333fc70d98671480a169332d4d63e414215973f7666ef5d85182c37086574ca945bd5bfca60676 languageName: node linkType: hard -"mjml-image@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-image@npm:4.14.1" +"mjml-image@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-image@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 1ad0910300b115fcc42de6d642ce35b2a3593ac1a431498a2a2f3210733ff7c2e4bc33334abbd20f9854c77aa0f7c859928941fa6cb0bce190453f857e7c7f90 + mjml-core: 4.15.3 + checksum: 79e7cf3769740f9667b4e758d0040089e63b080c163b50132acd94e97f852d094a8a31365dc4e576c9c5fb6af44da98398f8dcbf269b20c663082411d71227bd languageName: node linkType: hard -"mjml-migrate@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-migrate@npm:4.14.1" +"mjml-migrate@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-migrate@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 js-beautify: ^1.6.14 lodash: ^4.17.21 - mjml-core: 4.14.1 - mjml-parser-xml: 4.14.1 - yargs: ^16.1.0 + mjml-core: 4.15.3 + mjml-parser-xml: 4.15.3 + yargs: ^17.7.2 bin: migrate: lib/cli.js - checksum: 6710d100d79fd0b066cfd2fd0a5f7e6d7ccbf309a31039f162a22ff7b69c0540e550325560737270b205a3a3cd4562603e6bc4a44424ca973c44168741c3f388 + checksum: 70819d0c7e8d319a33e77bf7ca2cf8e075ad0087495b41275398336d3e552f7919a141ba03d79e27deae37816cf9f17628b8980b84d9f00127c08686317c96ba languageName: node linkType: hard -"mjml-navbar@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-navbar@npm:4.14.1" +"mjml-navbar@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-navbar@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: b85ccb20a95575387b5ce65e317f9a25fe46c1d77bab506274d630950da6bcbec1034cf351887eb1aec10e6c0b8b926804fc20cbed99209de45d49ada736f969 + mjml-core: 4.15.3 + checksum: 934f60b8ed369c84fdd52bdb662c3d36ae8ed698d670d84da94daa45044fb052da865b80d34e6bee143860a784bebd53ff8e5d13c8b0b69b06de84bc26dc92de languageName: node linkType: hard -"mjml-parser-xml@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-parser-xml@npm:4.14.1" +"mjml-parser-xml@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-parser-xml@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 - detect-node: 2.0.4 - htmlparser2: ^8.0.1 + "@babel/runtime": ^7.23.9 + detect-node: 2.1.0 + htmlparser2: ^9.1.0 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 + checksum: aa6364ad3f0d34d5f9ecb3200dc1a8eb8a5f062ddf2400857b8c3c7b19a4c370e730ea4b5d0b12e1f25ee76ce0254493847d936b06c60219e94239961b263c0f + languageName: node + linkType: hard + +"mjml-preset-core@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-preset-core@npm:4.15.3" + dependencies: + "@babel/runtime": ^7.23.9 + mjml-accordion: 4.15.3 + mjml-body: 4.15.3 + mjml-button: 4.15.3 + mjml-carousel: 4.15.3 + mjml-column: 4.15.3 + mjml-divider: 4.15.3 + mjml-group: 4.15.3 + mjml-head: 4.15.3 + mjml-head-attributes: 4.15.3 + mjml-head-breakpoint: 4.15.3 + mjml-head-font: 4.15.3 + mjml-head-html-attributes: 4.15.3 + mjml-head-preview: 4.15.3 + mjml-head-style: 4.15.3 + mjml-head-title: 4.15.3 + mjml-hero: 4.15.3 + mjml-image: 4.15.3 + mjml-navbar: 4.15.3 + mjml-raw: 4.15.3 + mjml-section: 4.15.3 + mjml-social: 4.15.3 + mjml-spacer: 4.15.3 + mjml-table: 4.15.3 + mjml-text: 4.15.3 + mjml-wrapper: 4.15.3 + checksum: 17e6d4d575d3a6a3f4dc0a68c8197001c899be88be5ed3d64b2b6e8ec3f5015cdfb785d48f00424058f2fdd2ddaf6d782afb87c6ef8d401717767d200a48219c + languageName: node + linkType: hard + +"mjml-raw@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-raw@npm:4.15.3" + dependencies: + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 65721432a89653644ae7e451e5a09d5168e6a69900f73823b74803ac4f4ff148ee4654db916e770e9e7a4e51cb83222c95b15b0220f21d96eeb9eb1a8571be7d + mjml-core: 4.15.3 + checksum: 644470bd445d219aa6effe2be27e210c0040d1e11206cd8608386bc3a0522a2d0d359acbda9157f2de548c94b0910332a2fcb907f5dcc84963bfcf3cd702659b languageName: node linkType: hard -"mjml-section@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-section@npm:4.14.1" +"mjml-section@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-section@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: f4b2ba3fa916193635b273d482a23e6f2f2969d01b5517e62d505ef5b6260e404bd2df3252ebd5926c1d5dc79f33cac8ceab19c161cf8435c3a23148c0296a15 + mjml-core: 4.15.3 + checksum: e4d9c3bfbcab792a7b149a01cbb1245f6afdf470178833ce3bcd924077f690616d829362ac920c4ea2d5ab950605b65f9d324b55b8b8a2fa3c4ff8e0cfac959a languageName: node linkType: hard -"mjml-social@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-social@npm:4.14.1" +"mjml-social@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-social@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 4d493dcb133beb6361cc5b6ff5799ef8456e39fd89f60d1c8ecc8767eb2fcfedf5f0a253dfafa543c6c3a32a798cb3e009b59e6588fdce5726b057435cf5d3a6 + mjml-core: 4.15.3 + checksum: 203aff07486caaf81c9807140ab0646c421f5ec7c8d6677de1cfd3b2f3e337f17ad6b1a5636cc0baa6df9c4f392fe5a8fa59202f4ce9675ee4dd7de1127abcdc languageName: node linkType: hard -"mjml-spacer@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-spacer@npm:4.14.1" +"mjml-spacer@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-spacer@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 93bf08f18da4a6593ded0675d32d0b2599d8fa9b00a3f3c0d90803106611f09a48efff803f82e740e27c8e5e56a36a40c66c87045ca7090ca5685762f0fe9382 + mjml-core: 4.15.3 + checksum: 8549c98f56fad5bad21d0d20fe2d2d02aa69e180a7d339b10f13b2c3ab371f9039f86154d9e338e906545b754672b1825bf464e1eb86040881d8410f0343fa62 languageName: node linkType: hard -"mjml-table@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-table@npm:4.14.1" +"mjml-table@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-table@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: f7fc1f648a112b8bab5209e9a3200926b1c10b39acc90f691e6b2e6d75a642ebf2f8f603b72676bd3490c3afaad97d06f1a64503dd971695f431760436317b26 + mjml-core: 4.15.3 + checksum: 71a667c962540848070e5811dd9ec852a536797af5bfc6c1a45f739e5cb2f1be82fd3bf750f0f5de6d21346882f90aa4c56052933eca79b8808985fd2d00a2f3 languageName: node linkType: hard -"mjml-text@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-text@npm:4.14.1" +"mjml-text@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-text@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - checksum: 16133c363813a4ec5bef06fbd34789a59d06206f78c43e43f1979bb326169b9f0809c4ddf651a05ae8ea4b295dcce6ad80d6c696b628832a5357d3bb532a2d5d + mjml-core: 4.15.3 + checksum: f1ff823233e17b5e417933c3f7a53a1d8a13e12e9f9456cf3c9674a8e12a7bf4a4558bbec33d2a14dc0c4578c5701c40b685e0b13de0f6bb297341665e5626c4 languageName: node linkType: hard -"mjml-validator@npm:4.13.0": - version: 4.13.0 - resolution: "mjml-validator@npm:4.13.0" +"mjml-validator@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-validator@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 - checksum: 40397cc664ee0e1ad884ddef30e2ab1cb3b14bb3fb1730e9ba8d7a786c25a260726b4bb70bae7094aa4177a369fd46bd2bf7f8e744f9cdecd0c3ceb8881b075e + "@babel/runtime": ^7.23.9 + checksum: 5b703bd27dc92cf6009ed62f6fe95a246ed564d1f188240011d9dd900a96dd313d437baf4ecd19baff0c0196927bf88eef5a9fc84f0473924f59d08946072816 languageName: node linkType: hard -"mjml-wrapper@npm:4.14.1": - version: 4.14.1 - resolution: "mjml-wrapper@npm:4.14.1" +"mjml-wrapper@npm:4.15.3": + version: 4.15.3 + resolution: "mjml-wrapper@npm:4.15.3" dependencies: - "@babel/runtime": ^7.14.6 + "@babel/runtime": ^7.23.9 lodash: ^4.17.21 - mjml-core: 4.14.1 - mjml-section: 4.14.1 - checksum: c3421fe6d783b4dfe617b37eae21aa3ff6e345ad06e18e8aeddd91e70bea75d277004feaf39d9af298e6e3ee550553df5110121d4486e1610ad51ae61a5ddf07 + mjml-core: 4.15.3 + mjml-section: 4.15.3 + checksum: d07ffac1c7ce6062fd846e89dc0143f90f9c052712a3d6c8ac1fa222fad3b73f8e1d95ffd93553fa648eeece8ad8ade782ec9999a6f3b020ca128a49892cf6a5 languageName: node linkType: hard "mjml@npm:^4.14.1": - version: 4.14.1 - resolution: "mjml@npm:4.14.1" - 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 + version: 4.15.3 + resolution: "mjml@npm:4.15.3" + dependencies: + "@babel/runtime": ^7.23.9 + mjml-cli: 4.15.3 + mjml-core: 4.15.3 + mjml-migrate: 4.15.3 + mjml-preset-core: 4.15.3 + mjml-validator: 4.15.3 bin: mjml: bin/mjml - checksum: 48906b077ea7283f77cec0baec422ebee133a5a2ea2c727c31e35f4b4e56894ef3134fb317704c12e4bc40632321779df19b950555bc49d188675e84dca7a826 + checksum: f85ecd1103feadd7df3344197d8c326ad738a880320175dee5a1efe2dd3da28693341a037bac3496f516bbb1f7635e81575a57642c4f16bc224afd3c2f77d60b languageName: node linkType: hard @@ -13814,15 +14340,15 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.2.0, mlly@npm:^1.4.2": - version: 1.6.1 - resolution: "mlly@npm:1.6.1" +"mlly@npm:^1.4.2, mlly@npm:^1.7.0": + version: 1.7.1 + resolution: "mlly@npm:1.7.1" dependencies: acorn: ^8.11.3 pathe: ^1.1.2 - pkg-types: ^1.0.3 - ufo: ^1.3.2 - checksum: c40a547dba8f6b2a5a840899d49f4c9550c233d47fd7bd75f4ac27f388047bad655ad86684329809c1640df4373b45bec77304f73530ca4354bc1199700e2a46 + pkg-types: ^1.1.1 + ufo: ^1.5.3 + checksum: 956a6d54119eef782f302580f63a9800654e588cd70015b4218a00069c6ef11b87984e8ffe140a4668b0100ad4022b11d1f9b11ac2c6dbafa4d8bc33ae3a08a8 languageName: node linkType: hard @@ -13838,23 +14364,24 @@ __metadata: "@semantic-release/exec": ^6.0.3 "@semantic-release/git": ^10.0.1 "@types/clamscan": ^2.0.8 - "@types/node": 20.7.1 - "@typescript-eslint/eslint-plugin": ^6.7.2 - "@typescript-eslint/parser": ^6.7.2 + "@types/node": ^20.12.12 + "@typescript-eslint/eslint-plugin": ^7.9.0 + "@typescript-eslint/parser": ^7.9.0 cross-env: ^7.0.3 cypress: ^13.6.4 cypress-slow-down: ^1.3.1 dotenv: ^16.1.4 - eslint: ^8.49.0 - eslint-config-next: ^13.4.19 + eslint: ^8.57.0 + eslint-config-next: ^13.5.6 eslint-config-prettier: ^9.0.0 - eslint-import-resolver-typescript: ^3.6.0 + eslint-import-resolver-typescript: ^3.6.1 eslint-plugin-cypress: ^2.15.1 - eslint-plugin-import: ^2.28.1 + eslint-plugin-import: ^2.29.1 eslint-plugin-jsx-a11y: ^6.7.1 - eslint-plugin-n: ^16.1.0 - eslint-plugin-simple-import-sort: ^10.0.0 - eslint-plugin-unused-imports: ^3.0.0 + eslint-plugin-n: ^16.6.2 + eslint-plugin-node: ^11.1.0 + eslint-plugin-simple-import-sort: ^12.1.0 + eslint-plugin-unused-imports: ^3.2.0 husky: ^8.0.3 lint-staged: ^14.0.1 node-talisman: ^1.29.10 @@ -13863,9 +14390,9 @@ __metadata: semantic-release-slack-bot: ^4.0.2 ts-node: ^10.9.1 type-fest: ^4.18.2 - typescript: ^5.2.2 - vite-tsconfig-paths: ^4.2.1 - vitest: ^1.4.0 + typescript: ^5.4.5 + vite-tsconfig-paths: ^4.3.2 + vitest: ^1.6.0 languageName: unknown linkType: soft @@ -13892,84 +14419,47 @@ __metadata: languageName: node linkType: hard -"mongodb@npm:3.7.4, mongodb@npm:^3.7.4": - version: 3.7.4 - resolution: "mongodb@npm:3.7.4" +"mongodb-connection-string-url@npm:^3.0.0": + version: 3.0.1 + resolution: "mongodb-connection-string-url@npm:3.0.1" dependencies: - bl: ^2.2.1 - bson: ^1.1.4 - denque: ^1.4.1 - optional-require: ^1.1.8 - safe-buffer: ^5.1.2 - saslprep: ^1.0.0 - dependenciesMeta: - saslprep: - optional: true + "@types/whatwg-url": ^11.0.2 + whatwg-url: ^13.0.0 + checksum: b0a3b9e619c53ce8c10452c6475dc1eeba4761ae1b293b1b37014acf609f44ab7057f084de8fceead9934dba2aad0a59315eab9371c1287dbaaf5aae48c6d371 + languageName: node + linkType: hard + +"mongodb@npm:^6.7.0": + version: 6.7.0 + resolution: "mongodb@npm:6.7.0" + dependencies: + "@mongodb-js/saslprep": ^1.1.5 + bson: ^6.7.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: - aws4: + "@aws-sdk/credential-providers": optional: true - bson-ext: + "@mongodb-js/zstd": + optional: true + gcp-metadata: optional: true kerberos: optional: true mongodb-client-encryption: optional: true - mongodb-extjson: - optional: true snappy: optional: true - checksum: e9b4e932f40029d2fc7b2247737f4fc6fc8951c0ac86530e19d305b58dc8a8251bb42a73af2e9da14fd606856bf240c80951fec9a870719481c0cf2d78327547 - languageName: node - linkType: hard - -"mongoose-legacy-pluralize@npm:1.0.2": - version: 1.0.2 - resolution: "mongoose-legacy-pluralize@npm:1.0.2" - peerDependencies: - mongoose: "*" - checksum: 8312c208824b8c2d9cd60562cbc06d0da54118ca5799dfacabc1aa0f41d9ee061b2e7877019bc9cf7204bd509de88e20158b08d98d98a459d8784af69b4d9f77 - languageName: node - linkType: hard - -"mongoose@npm:^5.13.20": - version: 5.13.21 - resolution: "mongoose@npm:5.13.21" - dependencies: - "@types/bson": 1.x || 4.0.x - "@types/mongodb": ^3.5.27 - bson: ^1.1.4 - kareem: 2.3.2 - mongodb: 3.7.4 - mongoose-legacy-pluralize: 1.0.2 - mpath: 0.8.4 - mquery: 3.2.5 - ms: 2.1.2 - optional-require: 1.0.x - regexp-clone: 1.0.0 - safe-buffer: 5.2.1 - sift: 13.5.2 - sliced: 1.0.1 - checksum: 0da2073481852c76e05c6f73fdeec20ff06b72b6f12387f7f3888af71bc9927dcf31cf338b13efbe49f309934fc5d40512acd6afd6378362a797a84776954b43 - languageName: node - linkType: hard - -"mpath@npm:0.8.4": - version: 0.8.4 - resolution: "mpath@npm:0.8.4" - checksum: 06ad1d443766626fa361b67a4eca9cd4c36a71e475e92e8a5c242dbbc9a911adac00ce971177843b48475356df609f847342548da7701a976a2ab4116135caf0 - languageName: node - linkType: hard - -"mquery@npm:3.2.5": - version: 3.2.5 - resolution: "mquery@npm:3.2.5" - dependencies: - bluebird: 3.5.1 - debug: 3.1.0 - regexp-clone: ^1.0.0 - safe-buffer: 5.1.2 - sliced: 1.0.1 - checksum: 3f8c80c36118e144148a3a41015a3a218e45bddabb33ba2630b50f50c31acf3c4e9f6c0ca11fa07e955a0fe11941d17ac8f03356d3e4eb0452034469d8dd1856 + socks: + optional: true + checksum: 11677b416ba2bd8c8835663445b89db7f32faca763c5c3ce6d9de246826b4796ec628c35e84d1dc0b3c11be9623a1ebd6ecdb8eb90a40eededb8bc4fd75e4693 languageName: node linkType: hard @@ -14020,7 +14510,7 @@ __metadata: languageName: node linkType: hard -"mute-stream@npm:~1.0.0": +"mute-stream@npm:^1.0.0, mute-stream@npm:~1.0.0": version: 1.0.0 resolution: "mute-stream@npm:1.0.0" checksum: 36fc968b0e9c9c63029d4f9dc63911950a3bdf55c9a87f58d3a266289b67180201cade911e7699f8b2fa596b34c9db43dad37649e3f7fdd13c3bb9edb0017ee7 @@ -14050,11 +14540,11 @@ __metadata: linkType: hard "nan@npm:^2.14.0": - version: 2.18.0 - resolution: "nan@npm:2.18.0" + version: 2.20.0 + resolution: "nan@npm:2.20.0" dependencies: node-gyp: latest - checksum: 4fe42f58456504eab3105c04a5cffb72066b5f22bd45decf33523cb17e7d6abc33cca2a19829407b9000539c5cb25f410312d4dc5b30220167a3594896ea6a0a + checksum: eb09286e6c238a3582db4d88c875db73e9b5ab35f60306090acd2f3acae21696c9b653368b4a0e32abcef64ee304a923d6223acaddd16169e5eaaf5c508fb533 languageName: node linkType: hard @@ -14187,7 +14677,7 @@ __metadata: languageName: node linkType: hard -"next-tick@npm:1, next-tick@npm:^1.1.0": +"next-tick@npm:^1.1.0": version: 1.1.0 resolution: "next-tick@npm:1.1.0" checksum: 83b5cf36027a53ee6d8b7f9c0782f2ba87f4858d977342bfc3c20c21629290a2111f8374d13a81221179603ffc4364f38374b5655d17b6a8f8a8c77bdea4fe8b @@ -14195,28 +14685,28 @@ __metadata: linkType: hard "next@npm:latest": - version: 14.0.4 - resolution: "next@npm:14.0.4" - dependencies: - "@next/env": 14.0.4 - "@next/swc-darwin-arm64": 14.0.4 - "@next/swc-darwin-x64": 14.0.4 - "@next/swc-linux-arm64-gnu": 14.0.4 - "@next/swc-linux-arm64-musl": 14.0.4 - "@next/swc-linux-x64-gnu": 14.0.4 - "@next/swc-linux-x64-musl": 14.0.4 - "@next/swc-win32-arm64-msvc": 14.0.4 - "@next/swc-win32-ia32-msvc": 14.0.4 - "@next/swc-win32-x64-msvc": 14.0.4 - "@swc/helpers": 0.5.2 + version: 14.2.4 + resolution: "next@npm:14.2.4" + dependencies: + "@next/env": 14.2.4 + "@next/swc-darwin-arm64": 14.2.4 + "@next/swc-darwin-x64": 14.2.4 + "@next/swc-linux-arm64-gnu": 14.2.4 + "@next/swc-linux-arm64-musl": 14.2.4 + "@next/swc-linux-x64-gnu": 14.2.4 + "@next/swc-linux-x64-musl": 14.2.4 + "@next/swc-win32-arm64-msvc": 14.2.4 + "@next/swc-win32-ia32-msvc": 14.2.4 + "@next/swc-win32-x64-msvc": 14.2.4 + "@swc/helpers": 0.5.5 busboy: 1.6.0 - caniuse-lite: ^1.0.30001406 + caniuse-lite: ^1.0.30001579 graceful-fs: ^4.2.11 postcss: 8.4.31 styled-jsx: 5.1.1 - watchpack: 2.4.0 peerDependencies: "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.41.2 react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 @@ -14242,11 +14732,13 @@ __metadata: peerDependenciesMeta: "@opentelemetry/api": optional: true + "@playwright/test": + optional: true sass: optional: true bin: next: dist/bin/next - checksum: 879842979d3c7e2d2e2cd3edad3e715d408060a286bb12299089e08d7142af9effceee877e6d18aad359983119d025298ec5c63dd6317443027b47dc5167ac40 + checksum: 3b858cfec2e061d811811921361855659b09424ea4178cf0f4a0bbe5d3978b45da6f04575fe213d76e47f626439db61591b79932f37ff984b7b7de87dd1ccce0 languageName: node linkType: hard @@ -14260,13 +14752,13 @@ __metadata: linkType: hard "nock@npm:^13.3.3": - version: 13.4.0 - resolution: "nock@npm:13.4.0" + version: 13.5.4 + resolution: "nock@npm:13.5.4" dependencies: debug: ^4.1.0 json-stringify-safe: ^5.0.1 propagate: ^2.0.0 - checksum: 30c3751854f9c412df5f99e01eeaef25b2583d3cae80b8c46524acb39d8b7fa61043603472ad94a3adc4b7d1e0f3098e6bb06e787734cbfbde2751891115b311 + checksum: d31f924e34c87ae985edfb7b5a56e8a4dcfc3a072334ceb6d686326581f93090b3e23492663a64ce61b8df4f365b113231d926bc300bcfe9e5eb309c3e4b8628 languageName: node linkType: hard @@ -14293,7 +14785,7 @@ __metadata: languageName: node linkType: hard -"node-gyp@npm:^9.0.0, node-gyp@npm:^9.4.0": +"node-gyp@npm:^9.0.0, node-gyp@npm:^9.4.1": version: 9.4.1 resolution: "node-gyp@npm:9.4.1" dependencies: @@ -14315,8 +14807,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 @@ -14330,13 +14822,13 @@ __metadata: which: ^4.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + checksum: 72e2ab4b23fc32007a763da94018f58069fc0694bf36115d49a2b195c8831e12cf5dd1e7a3718fa85c06969aedf8fc126722d3b672ec1cb27e06ed33caee3c60 languageName: node linkType: hard "node-talisman@npm:^1.29.10": - version: 1.29.10 - resolution: "node-talisman@npm:1.29.10" + version: 1.29.11 + resolution: "node-talisman@npm:1.29.11" dependencies: clogy: ^1.3.3 exec-sh: ^0.3.4 @@ -14344,7 +14836,7 @@ __metadata: request: ^2.88.2 bin: node-talisman: dist-node/index.bin.js - checksum: bc787209f460f813d53d082a01b816abbcf22283603797a84a6918247461ed9512241f52087605869d770cd3b050a0d3a0c2c4f74368ccf826366d8f1b99eae6 + checksum: a77999e7ea65c29e525fb5454041b1a5a3caff612380e58a6fc076c92df76aff0661924f7e4b42c46b5ba0a868dfaa123c97091fb6804bef61f96c68b63ff1e4 languageName: node linkType: hard @@ -14358,9 +14850,9 @@ __metadata: linkType: hard "nodemailer@npm:^6.9.5": - version: 6.9.8 - resolution: "nodemailer@npm:6.9.8" - checksum: 6499b93b7070a1b789ec00681ccbbf34180f127f1ce455b28201584b0974086a86be858062d41044df72ed7aba5649a40321a8e926367d2a1dfc0e65b7bf8838 + version: 6.9.13 + resolution: "nodemailer@npm:6.9.13" + checksum: 1b591ef480be2ff69480127cbff819e6593b1ef263b6f920e1a4e83e40280582daf7a14a809ef92f9828e2a70bdb3ce22b11924e209f2afe4975f9ff37e08e9d languageName: node linkType: hard @@ -14376,13 +14868,13 @@ __metadata: linkType: hard "nopt@npm:^7.0.0, nopt@npm:^7.2.0": - version: 7.2.0 - resolution: "nopt@npm:7.2.0" + version: 7.2.1 + resolution: "nopt@npm:7.2.1" dependencies: abbrev: ^2.0.0 bin: nopt: bin/nopt.js - checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 + checksum: 6fa729cc77ce4162cfad8abbc9ba31d4a0ff6850c3af61d59b505653bef4781ec059f8890ecfe93ee8aa0c511093369cca88bfc998101616a2904e715bbbb7c9 languageName: node linkType: hard @@ -14423,14 +14915,14 @@ __metadata: linkType: hard "normalize-package-data@npm:^6.0.0": - version: 6.0.0 - resolution: "normalize-package-data@npm:6.0.0" + version: 6.0.1 + resolution: "normalize-package-data@npm:6.0.1" dependencies: hosted-git-info: ^7.0.0 is-core-module: ^2.8.1 semver: ^7.3.5 validate-npm-package-license: ^3.0.4 - checksum: 741211a4354ba6d618caffa98f64e0e5ec9e5575bf3aefe47f4b68e662d65f9ba1b6b2d10640c16254763ed0879288155566138b5ffe384172352f6e969c1752 + checksum: 4f6bca00b5092b824e1d4a28fb47052b41afaaebabfd0700e47f130cac619d60668aa6ff34dfa9bccc1b06c7adcef44c34a565576b63b578e1e35b3fc67c22ca languageName: node linkType: hard @@ -14456,9 +14948,9 @@ __metadata: linkType: hard "normalize-url@npm:^8.0.0": - version: 8.0.0 - resolution: "normalize-url@npm:8.0.0" - checksum: 24c20b75ebfd526d8453084692720b49d111c63c0911f1b7447427829597841eef5a8ba3f6bb93d6654007b991c1f5cd85da2c907800e439e2e2ec6c2abd0fc0 + version: 8.0.1 + resolution: "normalize-url@npm:8.0.1" + checksum: 43ea9ef0d6d135dd1556ab67aa4b74820f0d9d15aa504b59fa35647c729f1147dfce48d3ad504998fd1010f089cfb82c86c6d9126eb5c5bd2e9bd25f3a97749b languageName: node linkType: hard @@ -14519,15 +15011,15 @@ __metadata: linkType: hard "npm-bundled@npm:^3.0.0": - version: 3.0.0 - resolution: "npm-bundled@npm:3.0.0" + version: 3.0.1 + resolution: "npm-bundled@npm:3.0.1" dependencies: npm-normalize-package-bin: ^3.0.0 - checksum: 110859c2d6dcd7941dac0932a29171cbde123060486a4b6e897aaf5e025abeb3d9ffcdfe9e9271992e6396b2986c2c534f1029a45a7c196f1257fa244305dbf8 + checksum: 1f4f7307d0ff2fbd31638689490f1fd673a4540cd1d027c7c5d15e484c71d63c4b27979944b6f8738035260cf5a5477ebaae75b08818420508e7cf317d71416e languageName: node linkType: hard -"npm-install-checks@npm:^6.0.0, npm-install-checks@npm:^6.2.0": +"npm-install-checks@npm:^6.0.0, npm-install-checks@npm:^6.2.0, npm-install-checks@npm:^6.3.0": version: 6.3.0 resolution: "npm-install-checks@npm:6.3.0" dependencies: @@ -14620,24 +15112,24 @@ __metadata: linkType: hard "npm-run-path@npm:^5.1.0": - version: 5.2.0 - resolution: "npm-run-path@npm:5.2.0" + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" dependencies: path-key: ^4.0.0 - checksum: c5325e016014e715689c4014f7e0be16cc4cbf529f32a1723e511bc4689b5f823b704d2bca61ac152ce2bda65e0205dc8b3ba0ec0f5e4c3e162d302f6f5b9efb + checksum: ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 languageName: node linkType: hard "npm-user-validate@npm:^2.0.0": - version: 2.0.0 - resolution: "npm-user-validate@npm:2.0.0" - checksum: 52c0c64cb2b46e662d6dca36367ff68825b1c0aaa3962623962eec17988fd87b2064733d72670c0a963d880efd0b2966dec1f2aa2f8a3f4113af3efccd33f3bf + version: 2.0.1 + resolution: "npm-user-validate@npm:2.0.1" + checksum: 5350dc90bf15f094a5b64e6a78f808c489e4ab80c1db9701cf49bbfe4b883024cb90f2bc3d193ccb8960d8d259745dc57e1eb5c70884246409551befb4504387 languageName: node linkType: hard "npm@npm:^9.5.0": - version: 9.9.2 - resolution: "npm@npm:9.9.2" + version: 9.9.3 + resolution: "npm@npm:9.9.3" dependencies: "@isaacs/string-locale-compare": ^1.1.0 "@npmcli/arborist": ^6.5.0 @@ -14649,21 +15141,21 @@ __metadata: "@npmcli/run-script": ^6.0.2 abbrev: ^2.0.0 archy: ~1.0.0 - cacache: ^17.1.3 + cacache: ^17.1.4 chalk: ^5.3.0 - ci-info: ^3.8.0 + ci-info: ^4.0.0 cli-columns: ^4.0.0 cli-table3: ^0.6.3 columnify: ^1.6.0 fastest-levenshtein: ^1.0.16 - fs-minipass: ^3.0.2 - glob: ^10.2.7 + fs-minipass: ^3.0.3 + glob: ^10.3.10 graceful-fs: ^4.2.11 hosted-git-info: ^6.1.1 ini: ^4.1.1 init-package-json: ^5.0.0 is-cidr: ^4.0.2 - json-parse-even-better-errors: ^3.0.0 + json-parse-even-better-errors: ^3.0.1 libnpmaccess: ^7.0.2 libnpmdiff: ^5.0.20 libnpmexec: ^6.0.4 @@ -14677,14 +15169,14 @@ __metadata: libnpmversion: ^4.0.2 make-fetch-happen: ^11.1.1 minimatch: ^9.0.3 - minipass: ^5.0.0 + minipass: ^7.0.4 minipass-pipeline: ^1.2.4 ms: ^2.1.2 - node-gyp: ^9.4.0 + node-gyp: ^9.4.1 nopt: ^7.2.0 normalize-package-data: ^5.0.0 npm-audit-report: ^5.0.0 - npm-install-checks: ^6.2.0 + npm-install-checks: ^6.3.0 npm-package-arg: ^10.1.0 npm-pick-manifest: ^8.0.2 npm-profile: ^7.0.1 @@ -14697,12 +15189,12 @@ __metadata: proc-log: ^3.0.0 qrcode-terminal: ^0.12.0 read: ^2.1.0 - semver: ^7.5.4 + semver: ^7.6.0 sigstore: ^1.9.0 spdx-expression-parse: ^3.0.1 - ssri: ^10.0.4 + ssri: ^10.0.5 supports-color: ^9.4.0 - tar: ^6.1.15 + tar: ^6.2.0 text-table: ~0.2.0 tiny-relative-date: ^1.3.0 treeverse: ^3.0.0 @@ -14712,7 +15204,7 @@ __metadata: bin: npm: bin/npm-cli.js npx: bin/npx-cli.js - checksum: 1a95c2c27365fe2dc968132016116921f33e46fb8f45c21b74e9d277b84d00f1abf2eb27e5ee1bfec0f03ce6dc6e145efbc75539092724052944c7e058591c1b + checksum: 0ee7d2d901348ae5c3e2584eaf8647e99606b57dcfaadeba686ccfbcf0489b83ef10596af29da2ea1632aa561757f809a2699230d85b7726fd59ffbcbfee6ce7 languageName: node linkType: hard @@ -14749,13 +15241,6 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.7": - version: 2.2.7 - resolution: "nwsapi@npm:2.2.7" - checksum: cab25f7983acec7e23490fec3ef7be608041b460504229770e3bfcf9977c41d6fe58f518994d3bd9aa3a101f501089a3d4a63536f4ff8ae4b8c4ca23bdbfda4e - languageName: node - linkType: hard - "oauth-sign@npm:~0.9.0": version: 0.9.0 resolution: "oauth-sign@npm:0.9.0" @@ -14770,14 +15255,14 @@ __metadata: languageName: node linkType: hard -"object-code@npm:1.3.2": - version: 1.3.2 - resolution: "object-code@npm:1.3.2" - checksum: 9ee737965887bbb5ea21f322dbc186a09890615058fe9d02f1a94b72c57b90c29374cd866d7c2d8d846568fbb729bd20c6ab0d7779b264539bc0d6773f5c8bbc +"object-code@npm:1.3.3": + version: 1.3.3 + resolution: "object-code@npm:1.3.3" + checksum: 5f5602040a9d0e0f5e60e37340a21d8ab3d41309c7b7f63eeccf4d385686d8e1b408090f2a35899a84d740fbf6e243599208349027060b71f9911099a47714f8 languageName: node linkType: hard -"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0": +"object-inspect@npm:^1.13.1": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f @@ -14785,12 +15270,12 @@ __metadata: linkType: hard "object-is@npm:^1.1.2, object-is@npm:^1.1.5": - version: 1.1.5 - resolution: "object-is@npm:1.1.5" + version: 1.1.6 + resolution: "object-is@npm:1.1.6" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + call-bind: ^1.0.7 + define-properties: ^1.2.1 + checksum: 3ea22759967e6f2380a2cbbd0f737b42dc9ddb2dfefdb159a1b927fea57335e1b058b564bfa94417db8ad58cddab33621a035de6f5e5ad56d89f2dd03e66c6a1 languageName: node linkType: hard @@ -14801,7 +15286,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -14813,58 +15298,59 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.2, object.entries@npm:^1.1.6, object.entries@npm:^1.1.7": - version: 1.1.7 - resolution: "object.entries@npm:1.1.7" +"object.entries@npm:^1.1.2, object.entries@npm:^1.1.7, object.entries@npm:^1.1.8": + version: 1.1.8 + resolution: "object.entries@npm:1.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: da287d434e7e32989586cd734382364ba826a2527f2bc82e6acbf9f9bfafa35d51018b66ec02543ffdfa2a5ba4af2b6f1ca6e588c65030cb4fd9c67d6ced594c + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 5314877cb637ef3437a30bba61d9bacdb3ce74bf73ac101518be0633c37840c8cc67407edb341f766e8093b3d7516d5c3358f25adfee4a2c697c0ec4c8491907 languageName: node linkType: hard -"object.fromentries@npm:^2.0.6, object.fromentries@npm:^2.0.7": - version: 2.0.7 - resolution: "object.fromentries@npm:2.0.7" +"object.fromentries@npm:^2.0.7, object.fromentries@npm:^2.0.8": + version: 2.0.8 + resolution: "object.fromentries@npm:2.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 7341ce246e248b39a431b87a9ddd331ff52a454deb79afebc95609f94b1f8238966cf21f52188f2a353f0fdf83294f32f1ebf1f7826aae915ebad21fd0678065 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: 29b2207a2db2782d7ced83f93b3ff5d425f901945f3665ffda1821e30a7253cd1fd6b891a64279976098137ddfa883d748787a6fea53ecdb51f8df8b8cec0ae1 languageName: node linkType: hard "object.groupby@npm:^1.0.1": - version: 1.0.1 - resolution: "object.groupby@npm:1.0.1" + version: 1.0.3 + resolution: "object.groupby@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 - checksum: d7959d6eaaba358b1608066fc67ac97f23ce6f573dc8fc661f68c52be165266fcb02937076aedb0e42722fdda0bdc0bbf74778196ac04868178888e9fd3b78b5 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + checksum: 0d30693ca3ace29720bffd20b3130451dca7a56c612e1926c0a1a15e4306061d84410bdb1456be2656c5aca53c81b7a3661eceaa362db1bba6669c2c9b6d1982 languageName: node linkType: hard -"object.hasown@npm:^1.1.2": - version: 1.1.3 - resolution: "object.hasown@npm:1.1.3" +"object.hasown@npm:^1.1.4": + version: 1.1.4 + resolution: "object.hasown@npm:1.1.4" dependencies: - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 76bc17356f6124542fb47e5d0e78d531eafa4bba3fc2d6fc4b1a8ce8b6878912366c0d99f37ce5c84ada8fd79df7aa6ea1214fddf721f43e093ad2df51f27da1 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: bc46eb5ca22106fcd07aab1411508c2c68b7565fe8fb272f166fb9bf203972e8b5c86a5a4b2c86204beead0626a7a4119d32cefbaf7c5dd57b400bf9e6363cb6 languageName: node linkType: hard -"object.values@npm:^1.1.0, object.values@npm:^1.1.5, object.values@npm:^1.1.6, object.values@npm:^1.1.7": - version: 1.1.7 - resolution: "object.values@npm:1.1.7" +"object.values@npm:^1.1.0, object.values@npm:^1.1.5, object.values@npm:^1.1.6, object.values@npm:^1.1.7, object.values@npm:^1.2.0": + version: 1.2.0 + resolution: "object.values@npm:1.2.0" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: f3e4ae4f21eb1cc7cebb6ce036d4c67b36e1c750428d7b7623c56a0db90edced63d08af8a316d81dfb7c41a3a5fa81b05b7cc9426e98d7da986b1682460f0777 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa languageName: node linkType: hard @@ -14943,41 +15429,25 @@ __metadata: linkType: hard "openapi3-ts@npm:^4.1.2": - version: 4.2.1 - resolution: "openapi3-ts@npm:4.2.1" - dependencies: - yaml: ^2.3.4 - checksum: ba6fbaa11521879e825679ddd748d59d7927bd36ab50dd4cb44eb450cd04df159da26859e132d2c19503351451d3d4a100506a74eeca7441afa5b9ef9b87ab5b - languageName: node - linkType: hard - -"optional-require@npm:1.0.x": - version: 1.0.3 - resolution: "optional-require@npm:1.0.3" - checksum: 113d376ee2a130afbca1610c17f25f4d1d7c7e42029f3b4d56334ee5408fec2c3fe31617abdb699025cced274d75fd6f0b2ed5eb49bec47acabeecc3feb76f19 - languageName: node - linkType: hard - -"optional-require@npm:^1.1.8": - version: 1.1.8 - resolution: "optional-require@npm:1.1.8" + version: 4.3.3 + resolution: "openapi3-ts@npm:4.3.3" dependencies: - require-at: ^1.0.6 - checksum: 437db76f713052925185ae80837b593877f75101154e8937f50d33b0b07bd500c214efc9016748642109b6e3e1197eb0513a2963eb06bcf3890f88a2724b1c87 + yaml: ^2.4.5 + checksum: 6620742dbf57e22a1de47b43149ddbcc7c63d270cd2f796ccd7ab3ca9c1712c19259516f827e541c7d57c21a56eaa03d9d8b9fe07ec968d1c47493d60b02f209 languageName: node linkType: hard "optionator@npm:^0.9.3": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" + version: 0.9.4 + resolution: "optionator@npm:0.9.4" dependencies: - "@aashutoshrathi/word-wrap": ^1.2.3 deep-is: ^0.1.3 fast-levenshtein: ^2.0.6 levn: ^0.4.1 prelude-ls: ^1.2.1 type-check: ^0.4.0 - checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + word-wrap: ^1.2.5 + checksum: ecbd010e3dc73e05d239976422d9ef54a82a13f37c11ca5911dff41c98a6c7f0f163b27f922c37e7f8340af9d36febd3b6e9cef508f3339d4c393d7276d716bb languageName: node linkType: hard @@ -15170,9 +15640,9 @@ __metadata: linkType: hard "p-map@npm:^7.0.1": - version: 7.0.1 - resolution: "p-map@npm:7.0.1" - checksum: 553c218f582b9c7f96159dd55d082fc6df386ea86a78a3798b768f87f761d6f01ea52dd76225e69199720fa0684901d38353cd0978a39ef4f7f4fd287c4e9262 + version: 7.0.2 + resolution: "p-map@npm:7.0.2" + checksum: bc128c2b244ef5d4619392b2247d718a3fe471d5fa4a73834fd96182a237f460ec7e0ad0f95139ef7103a6b50ed164228c62e2f8e41ba2b15360fe1c20d13563 languageName: node linkType: hard @@ -15240,6 +15710,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea + languageName: node + linkType: hard + "pacote@npm:^15.0.0, pacote@npm:^15.0.8, pacote@npm:^15.2.0": version: 15.2.0 resolution: "pacote@npm:15.2.0" @@ -15446,13 +15923,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.10.1, path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" dependencies: - lru-cache: ^9.1.1 || ^10.0.0 + lru-cache: ^10.2.0 minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + checksum: 890d5abcd593a7912dcce7cf7c6bf7a0b5648e3dee6caf0712c126ca0a65c7f3d7b9d769072a4d1baf370f61ce493ab5b038d59988688e0c5f3f646ee3c69023 languageName: node linkType: hard @@ -15477,7 +15954,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.0, pathe@npm:^1.1.1, pathe@npm:^1.1.2": +"pathe@npm:^1.1.1, pathe@npm:^1.1.2": version: 1.1.2 resolution: "pathe@npm:1.1.2" checksum: ec5f778d9790e7b9ffc3e4c1df39a5bb1ce94657a4e3ad830c1276491ca9d79f189f47609884671db173400256b005f4955f7952f52a2aeb5834ad5fb4faf134 @@ -15530,9 +16007,9 @@ __metadata: linkType: hard "picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 languageName: node linkType: hard @@ -15566,13 +16043,13 @@ __metadata: languageName: node linkType: hard -"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:v1.1.0": - version: 1.1.0 - resolution: "pino-abstract-transport@npm:1.1.0" +"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:^1.2.0": + version: 1.2.0 + resolution: "pino-abstract-transport@npm:1.2.0" dependencies: readable-stream: ^4.0.0 split2: ^4.0.0 - checksum: cc84caabee5647b5753ae484d5f63a1bca0f6e1791845e2db2b6d830a561c2b5dd1177720f68d78994c8a93aecc69f2729e6ac2bc871a1bf5bb4b0ec17210668 + checksum: 3336c51fb91ced5ef8a4bfd70a96e41eb6deb905698e83350dc71eedffb34795db1286d2d992ce1da2f6cd330a68be3f7e2748775a6b8a2ee3416796070238d6 languageName: node linkType: hard @@ -15600,31 +16077,31 @@ __metadata: languageName: node linkType: hard -"pino-std-serializers@npm:^6.0.0": - version: 6.2.2 - resolution: "pino-std-serializers@npm:6.2.2" - checksum: aeb0662edc46ec926de9961ed4780a4f0586bb7c37d212cd469c069639e7816887a62c5093bc93f260a4e0900322f44fc8ab1343b5a9fa2864a888acccdb22a4 +"pino-std-serializers@npm:^7.0.0": + version: 7.0.0 + resolution: "pino-std-serializers@npm:7.0.0" + checksum: 08cd1d7b7adc4cfca39e42c2d5fd21bcf4513153734e7b8fa278b0e9e9f62df78c4c202886343fe882a462539c931cb8110b661775ad7f7217c96856795b5a86 languageName: node linkType: hard -"pino@npm:^8.17.0": - version: 8.17.2 - resolution: "pino@npm:8.17.2" +"pino@npm:^9.0.0": + version: 9.2.0 + resolution: "pino@npm:9.2.0" dependencies: atomic-sleep: ^1.0.0 fast-redact: ^3.1.1 on-exit-leak-free: ^2.1.0 - pino-abstract-transport: v1.1.0 - pino-std-serializers: ^6.0.0 + pino-abstract-transport: ^1.2.0 + pino-std-serializers: ^7.0.0 process-warning: ^3.0.0 quick-format-unescaped: ^4.0.3 real-require: ^0.2.0 safe-stable-stringify: ^2.3.1 - sonic-boom: ^3.7.0 - thread-stream: ^2.0.0 + sonic-boom: ^4.0.1 + thread-stream: ^3.0.0 bin: pino: bin.js - checksum: fc769d3d7b1333de94d51815fbe2abc4a1cc07cb0252a399313e54e26c13da2c0a69b227c296bd95ed52660d7eaa993662a9bf270b7370d0f7553fdd38716b63 + checksum: d702a3f6ff031afc4b165fc3b514e35bd1864d691f27789225a165cd5d344acf08f21ceee4b7d55d522ede57ac9bcb661ce161d8e1510acbc1bfd32b0f56fe39 languageName: node linkType: hard @@ -15645,14 +16122,14 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.0.3": - version: 1.0.3 - resolution: "pkg-types@npm:1.0.3" +"pkg-types@npm:^1.0.3, pkg-types@npm:^1.1.1": + version: 1.1.1 + resolution: "pkg-types@npm:1.1.1" dependencies: - jsonc-parser: ^3.2.0 - mlly: ^1.2.0 - pathe: ^1.1.0 - checksum: 4b305c834b912ddcc8a0fe77530c0b0321fe340396f84cbb87aecdbc126606f47f2178f23b8639e71a4870f9631c7217aef52ffed0ae17ea2dbbe7e43d116a6e + confbox: ^0.1.7 + mlly: ^1.7.0 + pathe: ^1.1.2 + checksum: 78ee49eea8c03802ffbdc79dfb6a741f905a4053453280cd2f1149850523fdaf46d39ecb88c2c2f757cceb9883f234bb0e56371084b5895632bdb00ef0f7298f languageName: node linkType: hard @@ -15668,6 +16145,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: b32d403ece71e042385cc7856385cecf1cd8e144fa74d2f1de40d1e16035dba097bc189715925e79b67bdd1472796ff168d3a90d296356c9c94d272d5b95f3ae + languageName: node + linkType: hard + "postcss-load-config@npm:^4.0.1": version: 4.0.2 resolution: "postcss-load-config@npm:4.0.2" @@ -15687,12 +16171,12 @@ __metadata: linkType: hard "postcss-selector-parser@npm:^6.0.10": - version: 6.0.15 - resolution: "postcss-selector-parser@npm:6.0.15" + version: 6.1.0 + resolution: "postcss-selector-parser@npm:6.1.0" dependencies: cssesc: ^3.0.0 util-deprecate: ^1.0.2 - checksum: 57decb94152111004f15e27b9c61131eb50ee10a3288e7fcf424cebbb4aba82c2817517ae718f8b5d704ee9e02a638d4a2acff8f47685c295a33ecee4fd31055 + checksum: 449f614e6706421be307d8638183c61ba45bc3b460fe3815df8971dbb4d59c4087181940d879daee4a7a2daf3d86e915db1cce0c006dd68ca75b4087079273bd languageName: node linkType: hard @@ -15707,7 +16191,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.36": +"postcss@npm:^8.4.38": version: 8.4.38 resolution: "postcss@npm:8.4.38" dependencies: @@ -15733,11 +16217,11 @@ __metadata: linkType: hard "prettier@npm:^3.0.3": - version: 3.1.1 - resolution: "prettier@npm:3.1.1" + version: 3.3.2 + resolution: "prettier@npm:3.3.2" bin: prettier: bin/prettier.cjs - checksum: e386855e3a1af86a748e16953f168be555ce66d6233f4ba54eb6449b88eb0c6b2ca79441b11eae6d28a7f9a5c96440ce50864b9d5f6356d331d39d6bb66c648e + checksum: 5557d8caed0b182f68123c2e1e370ef105251d1dd75800fadaece3d061daf96b1389141634febf776050f9d732c7ae8fd444ff0b4a61b20535e7610552f32c69 languageName: node linkType: hard @@ -15793,6 +16277,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -15800,13 +16291,6 @@ __metadata: languageName: node linkType: hard -"process-warning@npm:^2.0.0": - version: 2.3.2 - resolution: "process-warning@npm:2.3.2" - checksum: cbeddc85d3963eccd6578b1eea5ba981383d1ec688d6e4ba5bf0ca6662d094c024b44dfcb1c530662c7694b68fe09fd95fa0269a1309090d793008f4553e7784 - languageName: node - linkType: hard - "process-warning@npm:^3.0.0": version: 3.0.0 resolution: "process-warning@npm:3.0.0" @@ -15860,22 +16344,24 @@ __metadata: linkType: hard "promzard@npm:^1.0.0": - version: 1.0.0 - resolution: "promzard@npm:1.0.0" + version: 1.0.2 + resolution: "promzard@npm:1.0.2" dependencies: - read: ^2.0.0 - checksum: c06948827171612faae321ebaf23ff8bd9ebb3e1e0f37616990bc4b81c663b192e447b3fe3b424211beb0062cec0cfe6ba3ce70c8b448b4aa59752b765dbb302 + read: ^3.0.1 + checksum: 08dee9179e79d4a6446f707cce46fb3e8e8d93ec8b8d722ddc1ec4043c4c07e2e88dc90c64326a58f83d1a7e2b0d6b3bdf11b8b2687b9c74bfb410bafe630ad8 languageName: node linkType: hard "prop-types-exact@npm:^1.2.0": - version: 1.2.0 - resolution: "prop-types-exact@npm:1.2.0" + version: 1.2.4 + resolution: "prop-types-exact@npm:1.2.4" dependencies: - has: ^1.0.3 - object.assign: ^4.1.0 - reflect.ownkeys: ^0.2.0 - checksum: 21676a16d5b2623c345ca938554faba7bf29c6ad589eac3f490eda2207bcfd8d25cb3dfda5e5f8e6805239aabd2c6943f7bfbe726a1de708bae2b7a01c03eead + es-errors: ^1.3.0 + hasown: ^2.0.2 + isarray: ^2.0.5 + object.assign: ^4.1.5 + reflect.ownkeys: ^1.1.4 + checksum: cbb76fab892d9e1e5711dad8acb7ffbffbcec6fc1df642e0fdd0c5756f37977fb75f689cee02370d7e790aad42bb9b20eb15a3304edc2b7f839c9a2a9f9a38e8 languageName: node linkType: hard @@ -15973,7 +16459,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 @@ -16008,11 +16494,11 @@ __metadata: linkType: hard "qs@npm:^6.11.0, qs@npm:^6.5.1": - version: 6.11.2 - resolution: "qs@npm:6.11.2" + version: 6.12.1 + resolution: "qs@npm:6.12.1" dependencies: - side-channel: ^1.0.4 - checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b + side-channel: ^1.0.6 + checksum: aa761d99e65b6936ba2dd2187f2d9976afbcda38deb3ff1b3fe331d09b0c578ed79ca2abdde1271164b5be619c521ec7db9b34c23f49a074e5921372d16242d5 languageName: node linkType: hard @@ -16105,15 +16591,15 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1": - version: 2.5.1 - resolution: "raw-body@npm:2.5.1" +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" dependencies: bytes: 3.1.2 http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - checksum: 5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e + checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 languageName: node linkType: hard @@ -16149,11 +16635,11 @@ __metadata: linkType: hard "rc-menu@npm:^9.0.14": - version: 9.12.4 - resolution: "rc-menu@npm:9.12.4" + version: 9.14.0 + resolution: "rc-menu@npm:9.14.0" dependencies: "@babel/runtime": ^7.10.1 - "@rc-component/trigger": ^1.17.0 + "@rc-component/trigger": ^2.0.0 classnames: 2.x rc-motion: ^2.4.3 rc-overflow: ^1.3.1 @@ -16161,21 +16647,21 @@ __metadata: peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 3d7770defb882a444b21d6c437b0cf8759226a98233a50d48d0554bf2addab05c67544466b54c9bcc641d7859e7a9be84031d3493a521b697d56c9b9c2a0e7f3 + checksum: 576f2bd3b49ede678e8584dbb7f0aa3c7461363b66c119fbec1b5a288349cc25f168d53f9f6488ba1cf25430917a63f131c4e503f474d91de6ce64fed2036137 languageName: node linkType: hard "rc-motion@npm:^2.0.0, rc-motion@npm:^2.4.3": - version: 2.9.0 - resolution: "rc-motion@npm:2.9.0" + version: 2.9.2 + resolution: "rc-motion@npm:2.9.2" dependencies: "@babel/runtime": ^7.11.1 classnames: ^2.2.1 - rc-util: ^5.21.0 + rc-util: ^5.43.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 6c7c211a62896a2c443c43f27d13ec84c832884ec1860a40025f6270321e4e8c8a7abaf99d60a09d6e5cadc112e3d9787e0c58970eb69b0bb798eaa6be81dcf5 + checksum: 704dceedaf7f75e884b6a6e1134e674c1351ee6c6b1bd6a18ff73594d1ba0379cab77abd7fcad7d842ca07595bfe0a7ab291210a7144f7fd2e5e68a199e1561c languageName: node linkType: hard @@ -16225,16 +16711,16 @@ __metadata: languageName: node linkType: hard -"rc-util@npm:^5.17.0, rc-util@npm:^5.19.2, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.26.0, rc-util@npm:^5.27.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0": - version: 5.38.1 - resolution: "rc-util@npm:5.38.1" +"rc-util@npm:^5.17.0, rc-util@npm:^5.19.2, rc-util@npm:^5.24.4, rc-util@npm:^5.26.0, rc-util@npm:^5.27.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.43.0": + version: 5.43.0 + resolution: "rc-util@npm:5.43.0" dependencies: "@babel/runtime": ^7.18.3 react-is: ^18.2.0 peerDependencies: react: ">=16.9.0" react-dom: ">=16.9.0" - checksum: 40d0411fb5d6b0a187e718ff16c18f3d68eae3d7e4def43a9a9b2690b89cfce639077a69d683aa01302f8132394dd633baf76b07e5a3b8438fb706b1abb31937 + checksum: 48c10afb5886aed86d1f5241883f972b2b16235b0cc4867a05d061324f107aa113260c34eeb13ad18f4b66d1264dbcb3baf725c8ea34fbdaa504410d4e71b3ce languageName: node linkType: hard @@ -16300,14 +16786,14 @@ __metadata: linkType: hard "react-dom@npm:latest": - version: 18.2.0 - resolution: "react-dom@npm:18.2.0" + version: 18.3.1 + resolution: "react-dom@npm:18.3.1" dependencies: loose-envify: ^1.1.0 - scheduler: ^0.23.0 + scheduler: ^0.23.2 peerDependencies: - react: ^18.2.0 - checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc + react: ^18.3.1 + checksum: 298954ecd8f78288dcaece05e88b570014d8f6dce5db6f66e6ee91448debeb59dcd31561dddb354eee47e6c1bb234669459060deb238ed0213497146e555a0b9 languageName: node linkType: hard @@ -16339,14 +16825,14 @@ __metadata: linkType: hard "react-focus-lock@npm:^2.9.4": - version: 2.9.6 - resolution: "react-focus-lock@npm:2.9.6" + version: 2.12.1 + resolution: "react-focus-lock@npm:2.12.1" dependencies: "@babel/runtime": ^7.0.0 - focus-lock: ^1.0.0 + focus-lock: ^1.3.5 prop-types: ^15.6.2 react-clientside-effect: ^1.2.6 - use-callback-ref: ^1.3.0 + use-callback-ref: ^1.3.2 use-sidecar: ^1.1.2 peerDependencies: "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -16354,7 +16840,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 3ee2b32dfe479839548baf097d53ddab0b9a8df71cd51763edc9dd900eb85ac98e0255130a9152de9a424a038bae6e1782fca6fde0d89ae1f37c2ca802d94351 + checksum: f95c575a904a4ccf0c856c0fdbb8614dd99edd6bd124932a25c62285c6e5374586d762f5ba9ac3b1a1b865e93e6c32ca7dee273a0b336ad112becf91150391c6 languageName: node linkType: hard @@ -16439,9 +16925,9 @@ __metadata: linkType: hard "react-is@npm:^18.0.0, react-is@npm:^18.2.0": - version: 18.2.0 - resolution: "react-is@npm:18.2.0" - checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 languageName: node linkType: hard @@ -16587,9 +17073,9 @@ __metadata: languageName: node linkType: hard -"react-remove-scroll-bar@npm:^2.3.4": - version: 2.3.4 - resolution: "react-remove-scroll-bar@npm:2.3.4" +"react-remove-scroll-bar@npm:^2.3.6": + version: 2.3.6 + resolution: "react-remove-scroll-bar@npm:2.3.6" dependencies: react-style-singleton: ^2.2.1 tslib: ^2.0.0 @@ -16599,15 +17085,15 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: b5ce5f2f98d65c97a3e975823ae4043a4ba2a3b63b5ba284b887e7853f051b5cd6afb74abde6d57b421931c52f2e1fdbb625dc858b1cb5a32c27c14ab85649d4 + checksum: e793fe110e2ea60d5724d0b60f09de1f6cd1b080df00df9e68bb9a1b985895830e703194647059fdc22402a67a89b7673a5260773b89bcd98031fd99bc91aefa languageName: node linkType: hard "react-remove-scroll@npm:^2.5.6": - version: 2.5.7 - resolution: "react-remove-scroll@npm:2.5.7" + version: 2.5.10 + resolution: "react-remove-scroll@npm:2.5.10" dependencies: - react-remove-scroll-bar: ^2.3.4 + react-remove-scroll-bar: ^2.3.6 react-style-singleton: ^2.2.1 tslib: ^2.1.0 use-callback-ref: ^1.3.0 @@ -16618,7 +17104,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: e0dbb6856beaed2cff4996d9ca62d775686ff72e3e9de34043034d932223b588993b2fc7a18644750dd3d73eb19bd3f2cedb8d91f0e424c1ef8403010da24b1d + checksum: 2a926718b93e783732a2b369fec1349beaa187e8110ff6fa41940668a2826e59de1ee617dfc2bb5bbf5ad3a186d06b388baf56f9f0553fcac76cf9cec4b83eb0 languageName: node linkType: hard @@ -16668,8 +17154,8 @@ __metadata: linkType: hard "react-use@npm:^17.3.1": - version: 17.4.2 - resolution: "react-use@npm:17.4.2" + version: 17.5.0 + resolution: "react-use@npm:17.5.0" dependencies: "@types/js-cookie": ^2.2.6 "@xobotyi/scrollbar-width": ^1.9.5 @@ -16688,7 +17174,7 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 1b15add951a80eee637045e5e769dd565edde47838da3d8d0e9a4a2cfd547eb59626b5c5b020ba3c067c01356d2042c5948c534a90729114a7fc7d1e18763d0c + checksum: d3164db313f27aa701dcf87177861db6e19624ea7dd8bc81805352af7f6bf04072010b9776da4ac458d6bd318759ee69b12763d96098d83c75b7d66ffc689e3a languageName: node linkType: hard @@ -16742,11 +17228,11 @@ __metadata: linkType: hard "react@npm:latest": - version: 18.2.0 - resolution: "react@npm:18.2.0" + version: 18.3.1 + resolution: "react@npm:18.3.1" dependencies: loose-envify: ^1.1.0 - checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b + checksum: a27bcfa8ff7c15a1e50244ad0d0c1cb2ad4375eeffefd266a64889beea6f6b64c4966c9b37d14ee32d6c9fcd5aa6ba183b6988167ab4d127d13e7cb5b386a376 languageName: node linkType: hard @@ -16857,6 +17343,15 @@ __metadata: languageName: node linkType: hard +"read@npm:^3.0.1": + version: 3.0.1 + resolution: "read@npm:3.0.1" + dependencies: + mute-stream: ^1.0.0 + checksum: 65fdc31c18f457b08a4f6eea3624cbbe82f82d5f297f256062278627ed897381d1637dd494ba7419dd3c5ed73fb21a4cef1342748c6e108b0f8fc7f627a0b281 + languageName: node + linkType: hard + "readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" @@ -16868,7 +17363,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.2, readable-stream@npm:^2.0.5, readable-stream@npm:^2.1.5, readable-stream@npm:^2.3.5, readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.2, readable-stream@npm:^2.0.5, readable-stream@npm:^2.1.5, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -16883,7 +17378,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^4.0.0, readable-stream@npm:^4.1.0": +"readable-stream@npm:^4.0.0": version: 4.5.2 resolution: "readable-stream@npm:4.5.2" dependencies: @@ -16942,23 +17437,30 @@ __metadata: linkType: hard "reflect.getprototypeof@npm:^1.0.4": - version: 1.0.4 - resolution: "reflect.getprototypeof@npm:1.0.4" + version: 1.0.6 + resolution: "reflect.getprototypeof@npm:1.0.6" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.1 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 globalthis: ^1.0.3 which-builtin-type: ^1.1.3 - checksum: 16e2361988dbdd23274b53fb2b1b9cefeab876c3941a2543b4cadac6f989e3db3957b07a44aac46cfceb3e06e2871785ec2aac992d824f76292f3b5ee87f66f2 + checksum: 88e9e65a7eaa0bf8e9a8bbf8ac07571363bc333ba8b6769ed5e013e0042ed7c385e97fae9049510b3b5fe4b42472d8f32de9ce8ce84902bc4297d4bbe3777dba languageName: node linkType: hard -"reflect.ownkeys@npm:^0.2.0": - version: 0.2.0 - resolution: "reflect.ownkeys@npm:0.2.0" - checksum: 9530b166569e547c2cf25ade3cdc39c662212feeccf3e0ed46e6d8abf92f5683c82d7857011cee6230bf648eb0b99b6b419a007012b8571dcd4bb4d818d3b88d +"reflect.ownkeys@npm:^1.1.4": + version: 1.1.4 + resolution: "reflect.ownkeys@npm:1.1.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + es-set-tostringtag: ^2.0.1 + globalthis: ^1.0.3 + checksum: 224da6673729dbf20751c1d7474cac475f0e9e04ad1f470f1e26c278fbb104657ae56cd125cb71dbdf6d66d6f8bfa04337c07b92a2524cdad6cb8dc581cdce29 languageName: node linkType: hard @@ -16969,21 +17471,22 @@ __metadata: languageName: node linkType: hard -"regexp-clone@npm:1.0.0, regexp-clone@npm:^1.0.0": - version: 1.0.0 - resolution: "regexp-clone@npm:1.0.0" - checksum: ca4960bbdc4237c84813b12aed351606be7db60a8c8867ef46b44f00eec4e83f51b31de34e294900517db9d7a39636117af80916f6ce7dc45ea00cae3c6d6fc3 +"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" + dependencies: + call-bind: ^1.0.6 + define-properties: ^1.2.1 + es-errors: ^1.3.0 + set-function-name: ^2.0.1 + checksum: d7f333667d5c564e2d7a97c56c3075d64c722c9bb51b2b4df6822b2e8096d623a5e63088fb4c83df919b6951ef8113841de8b47de7224872fa6838bc5d8a7d64 languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.1": - version: 1.5.1 - resolution: "regexp.prototype.flags@npm:1.5.1" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - set-function-name: ^2.0.0 - checksum: 869edff00288442f8d7fa4c9327f91d85f3b3acf8cbbef9ea7a220345cf23e9241b6def9263d2c1ebcf3a316b0aa52ad26a43a84aa02baca3381717b3e307f47 +"regexpp@npm:^3.0.0": + version: 3.2.0 + resolution: "regexpp@npm:3.2.0" + checksum: a78dc5c7158ad9ddcfe01aa9144f46e192ddbfa7b263895a70a5c6c73edd9ce85faf7c0430e59ac38839e1734e275b9c3de5c57ee3ab6edc0e0b1bdebefccef8 languageName: node linkType: hard @@ -17031,10 +17534,10 @@ __metadata: languageName: node linkType: hard -"remove-accents@npm:0.4.2": - version: 0.4.2 - resolution: "remove-accents@npm:0.4.2" - checksum: 84a6988555dea24115e2d1954db99509588d43fe55a1590f0b5894802776f7b488b3151c37ceb9e4f4b646f26b80b7325dcea2fae58bc3865df146e1fa606711 +"remove-accents@npm:0.5.0": + version: 0.5.0 + resolution: "remove-accents@npm:0.5.0" + checksum: 7045b37015acb03df406d21f9cbe93c3fcf2034189f5d2e33b1dace9c7d6bdcd839929905ced21a5d76c58553557e1a42651930728702312a5774179d5b9147b languageName: node linkType: hard @@ -17089,13 +17592,6 @@ __metadata: languageName: node linkType: hard -"require-at@npm:^1.0.6": - version: 1.0.6 - resolution: "require-at@npm:1.0.6" - checksum: 7753a6ebad99855ef015d5533a787c65e883c94c23371368eebf6f1c7e2a078811013b204823152cbab206a00e825e8e5ca09416fd835a489fa30bf064fbe6d9 - languageName: node - linkType: hard - "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -17170,7 +17666,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8, resolve@npm:^1.10.0, resolve@npm:^1.19.0, resolve@npm:^1.22.2, resolve@npm:^1.22.4": +"resolve@npm:1.22.8, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.19.0, resolve@npm:^1.22.2, resolve@npm:^1.22.4": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -17183,7 +17679,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^2.0.0-next.4": +"resolve@npm:^2.0.0-next.5": version: 2.0.0-next.5 resolution: "resolve@npm:2.0.0-next.5" dependencies: @@ -17196,7 +17692,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@1.22.8#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.22.2#~builtin, resolve@patch:resolve@^1.22.4#~builtin": +"resolve@patch:resolve@1.22.8#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.10.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.22.2#~builtin, resolve@patch:resolve@^1.22.4#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -17209,7 +17705,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^2.0.0-next.4#~builtin": +"resolve@patch:resolve@^2.0.0-next.5#~builtin": version: 2.0.0-next.5 resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#~builtin::version=2.0.0-next.5&hash=c3c19d" dependencies: @@ -17260,13 +17756,20 @@ __metadata: languageName: node linkType: hard -"ret@npm:^0.2.0, ret@npm:~0.2.0": +"ret@npm:^0.2.0": version: 0.2.2 resolution: "ret@npm:0.2.2" checksum: 774964bb413a3525e687bca92d81c1cd75555ec33147c32ecca22f3d06409e35df87952cfe3d57afff7650a0f7e42139cf60cb44e94c29dde390243bc1941f16 languageName: node linkType: hard +"ret@npm:~0.4.0": + version: 0.4.3 + resolution: "ret@npm:0.4.3" + checksum: 621c73c86db7537d91a2c47f602c7db71e11cd6f131fedb24aa2818b4d35a23377e0bc22bfa6f12295706d5b06035cf6e8d92fbd75f8f37d73b65e188b7f3fa9 + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -17282,13 +17785,13 @@ __metadata: linkType: hard "rfdc@npm:^1.1.4, rfdc@npm:^1.2.0, rfdc@npm:^1.3.0": - version: 1.3.0 - resolution: "rfdc@npm:1.3.0" - checksum: fb2ba8512e43519983b4c61bd3fa77c0f410eff6bae68b08614437bc3f35f91362215f7b4a73cbda6f67330b5746ce07db5dd9850ad3edc91271ad6deea0df32 + version: 1.4.1 + resolution: "rfdc@npm:1.4.1" + checksum: 3b05bd55062c1d78aaabfcea43840cdf7e12099968f368e9a4c3936beb744adb41cbdb315eac6d4d8c6623005d6f87fdf16d8a10e1ff3722e84afea7281c8d13 languageName: node linkType: hard -"rimraf@npm:3.0.2, rimraf@npm:^3.0.0, rimraf@npm:^3.0.2": +"rimraf@npm:3.0.2, rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -17339,22 +17842,25 @@ __metadata: linkType: hard "rollup@npm:^4.13.0": - version: 4.13.0 - resolution: "rollup@npm:4.13.0" - dependencies: - "@rollup/rollup-android-arm-eabi": 4.13.0 - "@rollup/rollup-android-arm64": 4.13.0 - "@rollup/rollup-darwin-arm64": 4.13.0 - "@rollup/rollup-darwin-x64": 4.13.0 - "@rollup/rollup-linux-arm-gnueabihf": 4.13.0 - "@rollup/rollup-linux-arm64-gnu": 4.13.0 - "@rollup/rollup-linux-arm64-musl": 4.13.0 - "@rollup/rollup-linux-riscv64-gnu": 4.13.0 - "@rollup/rollup-linux-x64-gnu": 4.13.0 - "@rollup/rollup-linux-x64-musl": 4.13.0 - "@rollup/rollup-win32-arm64-msvc": 4.13.0 - "@rollup/rollup-win32-ia32-msvc": 4.13.0 - "@rollup/rollup-win32-x64-msvc": 4.13.0 + version: 4.18.0 + resolution: "rollup@npm:4.18.0" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.18.0 + "@rollup/rollup-android-arm64": 4.18.0 + "@rollup/rollup-darwin-arm64": 4.18.0 + "@rollup/rollup-darwin-x64": 4.18.0 + "@rollup/rollup-linux-arm-gnueabihf": 4.18.0 + "@rollup/rollup-linux-arm-musleabihf": 4.18.0 + "@rollup/rollup-linux-arm64-gnu": 4.18.0 + "@rollup/rollup-linux-arm64-musl": 4.18.0 + "@rollup/rollup-linux-powerpc64le-gnu": 4.18.0 + "@rollup/rollup-linux-riscv64-gnu": 4.18.0 + "@rollup/rollup-linux-s390x-gnu": 4.18.0 + "@rollup/rollup-linux-x64-gnu": 4.18.0 + "@rollup/rollup-linux-x64-musl": 4.18.0 + "@rollup/rollup-win32-arm64-msvc": 4.18.0 + "@rollup/rollup-win32-ia32-msvc": 4.18.0 + "@rollup/rollup-win32-x64-msvc": 4.18.0 "@types/estree": 1.0.5 fsevents: ~2.3.2 dependenciesMeta: @@ -17368,12 +17874,18 @@ __metadata: optional: true "@rollup/rollup-linux-arm-gnueabihf": optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true "@rollup/rollup-linux-arm64-gnu": optional: true "@rollup/rollup-linux-arm64-musl": optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true "@rollup/rollup-linux-riscv64-gnu": optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true "@rollup/rollup-linux-x64-gnu": optional: true "@rollup/rollup-linux-x64-musl": @@ -17388,7 +17900,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: c2c35bee0a71ceb0df37c170c2b73a500bf9ebdffb747487d77831348603d50dcfcdd9d0a937362d3a87edda559c9d1e017fba2d75f05f0c594634d9b8dde9a4 + checksum: 54cde921e763017ce952ba76ec77d58dd9c01e3536c3be628d4af8c59d9b2f0e1e6a11b30fda44845c7b74098646cd972feb3bcd2f4a35d3293366f2eeb0a39e languageName: node linkType: hard @@ -17440,32 +17952,32 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.1": - version: 1.0.1 - resolution: "safe-array-concat@npm:1.0.1" +"safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + get-intrinsic: ^1.2.4 has-symbols: ^1.0.3 isarray: ^2.0.5 - checksum: 001ecf1d8af398251cbfabaf30ed66e3855127fbceee178179524b24160b49d15442f94ed6c0db0b2e796da76bb05b73bf3cc241490ec9c2b741b41d33058581 - languageName: node - linkType: hard - -"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + checksum: a3b259694754ddfb73ae0663829e396977b99ff21cbe8607f35a469655656da8e271753497e59da8a7575baa94d2e684bea3e10ddd74ba046c0c9b4418ffa0c4 languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 languageName: node linkType: hard +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + languageName: node + linkType: hard + "safe-json-stringify@npm:~1": version: 1.2.0 resolution: "safe-json-stringify@npm:1.2.0" @@ -17473,23 +17985,23 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-regex-test@npm:1.0.0" +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.1.3 + call-bind: ^1.0.6 + es-errors: ^1.3.0 is-regex: ^1.1.4 - checksum: bc566d8beb8b43c01b94e67de3f070fd2781685e835959bbbaaec91cc53381145ca91f69bd837ce6ec244817afa0a5e974fc4e40a2957f0aca68ac3add1ddd34 + checksum: 6c7d392ff1ae7a3ae85273450ed02d1d131f1d2c76e177d6b03eb88e6df8fa062639070e7d311802c1615f351f18dc58f9454501c58e28d5ffd9b8f502ba6489 languageName: node linkType: hard -"safe-regex2@npm:^2.0.0": - version: 2.0.0 - resolution: "safe-regex2@npm:2.0.0" +"safe-regex2@npm:^3.1.0": + version: 3.1.0 + resolution: "safe-regex2@npm:3.1.0" dependencies: - ret: ~0.2.0 - checksum: f5e182fca040dedd50ae052ea0eb035d9903b2db71243d5d8b43299735857288ef2ab52546a368d9c6fd1333b2a0d039297925e78ffc14845354f3f6158af7c2 + ret: ~0.4.0 + checksum: 4f9f7172662763619052a45599e515efc5dd10a932690f610c8ab808a4baa41be3feafefa444f7532651d721d12871a1c9a85330626cdd013b804e8f4240dff1 languageName: node linkType: hard @@ -17507,15 +18019,6 @@ __metadata: languageName: node linkType: hard -"saslprep@npm:^1.0.0": - version: 1.0.3 - resolution: "saslprep@npm:1.0.3" - dependencies: - sparse-bitfield: ^3.0.3 - checksum: 4fdc0b70fb5e523f977de405e12cca111f1f10dd68a0cfae0ca52c1a7919a94d1556598ba2d35f447655c3b32879846c77f9274c90806f6673248ae3cea6ee43 - languageName: node - linkType: hard - "sax@npm:1.2.1": version: 1.2.1 resolution: "sax@npm:1.2.1" @@ -17524,9 +18027,9 @@ __metadata: linkType: hard "sax@npm:>=0.6.0": - version: 1.3.0 - resolution: "sax@npm:1.3.0" - checksum: 238ab3a9ba8c8f8aaf1c5ea9120386391f6ee0af52f1a6a40bbb6df78241dd05d782f2359d614ac6aae08c4c4125208b456548a6cf68625aa4fe178486e63ecd + version: 1.4.1 + resolution: "sax@npm:1.4.1" + checksum: 3ad64df16b743f0f2eb7c38ced9692a6d924f1cd07bbe45c39576c2cf50de8290d9d04e7b2228f924c7d05fecc4ec5cf651423278e0c7b63d260c387ef3af84a languageName: node linkType: hard @@ -17539,12 +18042,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.23.0": - version: 0.23.0 - resolution: "scheduler@npm:0.23.0" +"scheduler@npm:^0.23.2": + version: 0.23.2 + resolution: "scheduler@npm:0.23.2" dependencies: loose-envify: ^1.1.0 - checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a + checksum: 3e82d1f419e240ef6219d794ff29c7ee415fbdc19e038f680a10c067108e06284f1847450a210b29bbaf97b9d8a97ced5f624c31c681248ac84c80d56ad5a2c4 languageName: node linkType: hard @@ -17650,7 +18153,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.4, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": +"semver@npm:7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -17661,7 +18164,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^6.3.1": +"semver@npm:^6.1.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -17670,6 +18173,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 40f6a95101e8d854357a644da1b8dd9d93ce786d5c6a77227bc69dbb17bea83d0d1d1d7c4cd5920a6df909f48e8bd8a5909869535007f90278289f2451d0292d + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" @@ -17738,6 +18250,7 @@ __metadata: axios-cache-interceptor: ^1.3.2 basic-ftp: ^5.0.3 boom: ^7.3.0 + bson: ^6.7.0 bunyan: ^1.8.15 bunyan-slack: ^0.0.10 burner-email-providers: ^1.0.67 @@ -17773,8 +18286,7 @@ __metadata: migrate-mongo: ^11.0.0 miniget: ^4.2.3 mjml: ^4.14.1 - mongodb: ^3.7.4 - mongoose: ^5.13.20 + mongodb: ^6.7.0 netmask: ^2.0.2 nodemailer: ^6.9.5 nodemailer-html-to-text: ^3.2.0 @@ -17791,11 +18303,12 @@ __metadata: supertest: ^6.3.3 tsup: ^7.2.0 type-fest: ^4.18.2 - typescript: ^5.2.2 + typescript: ^5.4.5 xlsx: ^0.18.5 xml2js: ^0.6.2 - zod: 3.21.4 + zod: 3.23.8 zod-fixture: ^2.5.0 + zod-mongodb-schema: ^1.0.2 languageName: unknown linkType: soft @@ -17813,26 +18326,29 @@ __metadata: languageName: node linkType: hard -"set-function-length@npm:^1.1.1": - version: 1.1.1 - resolution: "set-function-length@npm:1.1.1" +"set-function-length@npm:^1.2.1": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" dependencies: - define-data-property: ^1.1.1 - get-intrinsic: ^1.2.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 - checksum: c131d7569cd7e110cafdfbfbb0557249b538477624dfac4fc18c376d879672fa52563b74029ca01f8f4583a8acb35bb1e873d573a24edb80d978a7ee607c6e06 + has-property-descriptors: ^1.0.2 + checksum: a8248bdacdf84cb0fab4637774d9fb3c7a8e6089866d04c817583ff48e14149c87044ce683d7f50759a8c50fb87c7a7e173535b06169c87ef76f5fb276dfff72 languageName: node linkType: hard -"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" +"set-function-name@npm:^2.0.1, set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: ^1.0.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 functions-have-names: ^1.2.3 - has-property-descriptors: ^1.0.0 - checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f languageName: node linkType: hard @@ -17866,15 +18382,16 @@ __metadata: "@asteasolutions/zod-to-openapi": ^5.5.0 "@fastify/swagger": ^8.11.0 "@types/boom": ^7.3.3 - bson: ^1.1.4 + bson: ^6.7.0 dayjs: ^1.11.10 eslint-plugin-zod: ^1.4.0 lodash-es: ^4.17.21 luhn: ^2.4.1 - mongodb: ^3.7.4 + mongodb: ^6.7.0 type-fest: ^4.18.2 - typescript: ^5.2.2 - zod: 3.21.4 + typescript: ^5.4.5 + zod: 3.23.8 + zod-mongodb-schema: ^1.0.2 languageName: unknown linkType: soft @@ -17904,21 +18421,15 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" +"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" dependencies: - call-bind: ^1.0.0 - get-intrinsic: ^1.0.2 - object-inspect: ^1.9.0 - checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 - languageName: node - linkType: hard - -"sift@npm:13.5.2": - version: 13.5.2 - resolution: "sift@npm:13.5.2" - checksum: 31951836c464b995b25f888876dea9c58c7a3eaa419d2ed271776d55db2d1019c6438ee458047d3c16bc93f0a329366dc535dc3a6afc42038949dc2a6a548f61 + call-bind: ^1.0.7 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + object-inspect: ^1.13.1 + checksum: bfc1afc1827d712271453e91b7cd3878ac0efd767495fd4e594c4c2afaa7963b7b510e249572bfd54b0527e66e4a12b61b80c061389e129755f34c493aad9b97 languageName: node linkType: hard @@ -18037,13 +18548,6 @@ __metadata: languageName: node linkType: hard -"sliced@npm:1.0.1": - version: 1.0.1 - resolution: "sliced@npm:1.0.1" - checksum: 84528d23279985ead75809eeec5d601b0fb6bc28348c6627f4feb40747533a1e36a75e8bc60f9079528079b21c434890b397e8fc5c24a649165cc0bbe90b4d70 - languageName: node - linkType: hard - "slick@npm:^1.12.2": version: 1.12.2 resolution: "slick@npm:1.12.2" @@ -18069,37 +18573,46 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" dependencies: - agent-base: ^7.0.2 + agent-base: ^7.1.1 debug: ^4.3.4 socks: ^2.7.1 - checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 languageName: node linkType: hard "socks@npm:^2.6.2, socks@npm:^2.7.1": - version: 2.7.1 - resolution: "socks@npm:2.7.1" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: - ip: ^2.0.0 + ip-address: ^9.0.5 smart-buffer: ^4.2.0 - checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd languageName: node linkType: hard -"sonic-boom@npm:^3.0.0, sonic-boom@npm:^3.7.0": - version: 3.7.0 - resolution: "sonic-boom@npm:3.7.0" +"sonic-boom@npm:^3.0.0": + version: 3.8.1 + resolution: "sonic-boom@npm:3.8.1" + dependencies: + atomic-sleep: ^1.0.0 + checksum: 79c90d7a2f928489fd3d4b68d8f8d747a426ca6ccf83c3b102b36f899d4524463dd310982ab7ab6d6bcfd34b7c7c281ad25e495ad71fbff8fd6fa86d6273fc6b + languageName: node + linkType: hard + +"sonic-boom@npm:^4.0.1": + version: 4.0.1 + resolution: "sonic-boom@npm:4.0.1" dependencies: atomic-sleep: ^1.0.0 - checksum: 528f0f7f7e09dcdb02ad5985039f66554266cbd8813f9920781607c9248e01f468598c1334eab2cc740c016a63c8b2a20e15c3f618cddb08ea1cfb4a390a796e + checksum: 451b0f09bc0a0abfa6bfed0e2d7d36a6fa245be8a444a7ef1e3c8abb006e9994cb7530b1da39c8aee9033598d1ce187e244a6194c92a81790a2e2633c60cd63d languageName: node linkType: hard -"source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0": +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0": version: 1.2.0 resolution: "source-map-js@npm:1.2.0" checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 @@ -18163,9 +18676,9 @@ __metadata: linkType: hard "spdx-exceptions@npm:^2.1.0": - version: 2.3.0 - resolution: "spdx-exceptions@npm:2.3.0" - checksum: cb69a26fa3b46305637123cd37c85f75610e8c477b6476fa7354eb67c08128d159f1d36715f19be6f9daf4b680337deb8c65acdcae7f2608ba51931540687ac0 + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 languageName: node linkType: hard @@ -18180,9 +18693,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.16 - resolution: "spdx-license-ids@npm:3.0.16" - checksum: 5cdaa85aaa24bd02f9353a2e357b4df0a4f205cb35655f3fd0a5674a4fb77081f28ffd425379214bc3be2c2b7593ce1215df6bcc75884aeee0a9811207feabe2 + version: 3.0.18 + resolution: "spdx-license-ids@npm:3.0.18" + checksum: 457825df5dd1fc0135b0bb848c896143f70945cc2da148afc71c73ed0837d1d651f809006e406d82109c9dd71a8cb39785a3604815fe46bc0548e9d3976f6b69 languageName: node linkType: hard @@ -18220,6 +18733,13 @@ __metadata: languageName: node linkType: hard +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + "ssf@npm:~0.11.2": version: 0.11.2 resolution: "ssf@npm:0.11.2" @@ -18250,12 +18770,12 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^10.0.0, ssri@npm:^10.0.1, ssri@npm:^10.0.4": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" +"ssri@npm:^10.0.0, ssri@npm:^10.0.1, ssri@npm:^10.0.5": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" dependencies: minipass: ^7.0.3 - checksum: 0a31b65f21872dea1ed3f7c200d7bc1c1b91c15e419deca14f282508ba917cbb342c08a6814c7f68ca4ca4116dd1a85da2bbf39227480e50125a1ceffeecb750 + checksum: 4603d53a05bcd44188747d38f1cc43833b9951b5a1ee43ba50535bdfc5fe4a0897472dbe69837570a5417c3c073377ef4f8c1a272683b401857f72738ee57299 languageName: node linkType: hard @@ -18406,53 +18926,57 @@ __metadata: languageName: node linkType: hard -"string.prototype.matchall@npm:^4.0.8": - version: 4.0.10 - resolution: "string.prototype.matchall@npm:4.0.10" +"string.prototype.matchall@npm:^4.0.11": + version: 4.0.11 + resolution: "string.prototype.matchall@npm:4.0.11" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - get-intrinsic: ^1.2.1 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.4 + gopd: ^1.0.1 has-symbols: ^1.0.3 - internal-slot: ^1.0.5 - regexp.prototype.flags: ^1.5.0 - set-function-name: ^2.0.0 - side-channel: ^1.0.4 - checksum: 3c78bdeff39360c8e435d7c4c6ea19f454aa7a63eda95fa6fadc3a5b984446a2f9f2c02d5c94171ce22268a573524263fbd0c8edbe3ce2e9890d7cc036cdc3ed + internal-slot: ^1.0.7 + regexp.prototype.flags: ^1.5.2 + set-function-name: ^2.0.2 + side-channel: ^1.0.6 + checksum: 6ac6566ed065c0c8489c91156078ca077db8ff64d683fda97ae652d00c52dfa5f39aaab0a710d8243031a857fd2c7c511e38b45524796764d25472d10d7075ae languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.8": - version: 1.2.8 - resolution: "string.prototype.trim@npm:1.2.8" +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-object-atoms: ^1.0.0 + checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimend@npm:1.0.7" +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.7": - version: 1.0.7 - resolution: "string.prototype.trimstart@npm:1.0.7" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: df1007a7f580a49d692375d996521dc14fd103acda7f3034b3c558a60b82beeed3a64fa91e494e164581793a8ab0ae2f59578a49896a7af6583c1f20472bce96 languageName: node linkType: hard @@ -18553,11 +19077,11 @@ __metadata: linkType: hard "strip-literal@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-literal@npm:2.0.0" + version: 2.1.0 + resolution: "strip-literal@npm:2.1.0" dependencies: - js-tokens: ^8.0.2 - checksum: 1d0784408890cb8f7dca2b7658f7b8d6ea8e1e956475bffcb5b4ea0daa6ffb09335f4ff321562282eac4420feb791277bf2163a30ec81641845faee861d49625 + js-tokens: ^9.0.0 + checksum: 37c2072634d2de11a3644fe1bcf4abd566d85e89f0d8e8b10d35d04e7bef962e7c112fbe5b805ce63e59dfacedc240356eeef57976351502966b7c64b742c6ac languageName: node linkType: hard @@ -18595,9 +19119,9 @@ __metadata: linkType: hard "stylis@npm:^4.3.0": - version: 4.3.1 - resolution: "stylis@npm:4.3.1" - checksum: d365f1b008677b2147e8391e9cf20094a4202a5f9789562e7d9d0a3bd6f0b3067d39e8fd17cce5323903a56f6c45388e3d839e9c0bb5a738c91726992b14966d + version: 4.3.2 + resolution: "stylis@npm:4.3.2" + checksum: 0faa8a97ff38369f47354376cd9f0def9bf12846da54c28c5987f64aaf67dcb6f00dce88a8632013bfb823b2c4d1d62a44f4ac20363a3505a7ab4e21b70179fc languageName: node linkType: hard @@ -18637,7 +19161,7 @@ __metadata: languageName: node linkType: hard -"superagent@npm:^8.0.5": +"superagent@npm:^8.1.2": version: 8.1.2 resolution: "superagent@npm:8.1.2" dependencies: @@ -18665,12 +19189,12 @@ __metadata: linkType: hard "supertest@npm:^6.3.3": - version: 6.3.3 - resolution: "supertest@npm:6.3.3" + version: 6.3.4 + resolution: "supertest@npm:6.3.4" dependencies: methods: ^1.1.2 - superagent: ^8.0.5 - checksum: 38239e517f7ba62b7a139a79c5c48d55f8d67b5ff4b6e51d5b07732ca8bbc4a28ffa1b10916fbb403dd013a054dbf028edc5850057d9a43aecbff439d494673e + superagent: ^8.1.2 + checksum: 875c6fa7940f21e5be9bb646579cdb030d4057bf2da643e125e1f0480add1200395d2b17e10b8e54e1009efc63e047422501e9eb30e12828668498c0910f295f languageName: node linkType: hard @@ -18739,9 +19263,9 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.13, tar@npm:^6.1.15, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" +"tar@npm:^6.1.11, tar@npm:^6.1.13, tar@npm:^6.1.2, tar@npm:^6.2.0": + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: ^2.0.0 fs-minipass: ^2.0.0 @@ -18749,7 +19273,7 @@ __metadata: minizlib: ^2.1.1 mkdirp: ^1.0.3 yallist: ^4.0.0 - checksum: db4d9fe74a2082c3a5016630092c54c8375ff3b280186938cfd104f2e089c4fd9bad58688ef6be9cf186a889671bf355c7cda38f09bbf60604b281715ca57f5c + checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c languageName: node linkType: hard @@ -18811,12 +19335,12 @@ __metadata: languageName: node linkType: hard -"thread-stream@npm:^2.0.0": - version: 2.4.1 - resolution: "thread-stream@npm:2.4.1" +"thread-stream@npm:^3.0.0": + version: 3.1.0 + resolution: "thread-stream@npm:3.1.0" dependencies: real-require: ^0.2.0 - checksum: 8b28e11eab2f805f963e6b6b23afab5523079575c4fc79c16eb29aa1c13d7931289762ebbc1268b3373d3f35ce795bd291df8e2d51eb45779ecaaecd06873459 + checksum: 3c5b494ce776f832dfd696792cc865f78c1e850db93e07979349bbc1a5845857cd447aea95808892906cc0178a2fd3233907329f3376e7fc9951e2833f5b7896 languageName: node linkType: hard @@ -18861,19 +19385,19 @@ __metadata: linkType: hard "timers-ext@npm:^0.1.7": - version: 0.1.7 - resolution: "timers-ext@npm:0.1.7" + version: 0.1.8 + resolution: "timers-ext@npm:0.1.8" dependencies: - es5-ext: ~0.10.46 - next-tick: 1 - checksum: ef3f27a0702a88d885bcbb0317c3e3ecd094ce644da52e7f7d362394a125d9e3578292a8f8966071a980d8abbc3395725333b1856f3ae93835b46589f700d938 + es5-ext: ^0.10.64 + next-tick: ^1.1.0 + checksum: 7d37f90bdcee900aa4ba13e983905e2d16538bb13d38315f1ea3670656d91e7898f018909caedc8ebe964974ddeb3eedb5ffdc21f2329e34e6bcc353d0ee2903 languageName: node linkType: hard "tiny-invariant@npm:^1.0.0, tiny-invariant@npm:^1.0.6": - version: 1.3.1 - resolution: "tiny-invariant@npm:1.3.1" - checksum: 872dbd1ff20a21303a2fd20ce3a15602cfa7fcf9b228bd694a52e2938224313b5385a1078cb667ed7375d1612194feaca81c4ecbe93121ca1baebe344de4f84c + version: 1.3.3 + resolution: "tiny-invariant@npm:1.3.3" + checksum: 5e185c8cc2266967984ce3b352a4e57cb89dad5a8abb0dea21468a6ecaa67cd5bb47a3b7a85d08041008644af4f667fb8b6575ba38ba5fb00b3b5068306e59fe languageName: node linkType: hard @@ -18892,16 +19416,16 @@ __metadata: linkType: hard "tinybench@npm:^2.5.1": - version: 2.6.0 - resolution: "tinybench@npm:2.6.0" - checksum: a621ac66ac17ec5da7e9ac10b3c27040e58c3cd843ccedd8e1e3fab5702d6337b80d02b7bfbf420ab5f029dcb7895657fb80ce21181896e170fa4e6d2c2eebc4 + version: 2.8.0 + resolution: "tinybench@npm:2.8.0" + checksum: 024a307c6a71f6e2903e110952457ee3dfa606093b45d7f49efcfd01d452650e099474080677ff650b0fd76b49074425ac68ff2a70561699a78515a278bf0862 languageName: node linkType: hard -"tinypool@npm:^0.8.2": - version: 0.8.2 - resolution: "tinypool@npm:0.8.2" - checksum: b0993207b89ab8ab565e1eb03287aa3f15bc648c2e1da889bcfad003244271a5efe5c215d8074c3b8798ae7ea9c54678b6c9b09e7e5c8e82285177792e7ac30a +"tinypool@npm:^0.8.3": + version: 0.8.4 + resolution: "tinypool@npm:0.8.4" + checksum: d40c40e062d5eeae85dadc39294dde6bc7b9a7a7cf0c972acbbe5a2b42491dfd4c48381c1e48bbe02aff4890e63de73d115b2e7de2ce4c81356aa5e654a43caf languageName: node linkType: hard @@ -18929,11 +19453,9 @@ __metadata: linkType: hard "tmp@npm:~0.2.1": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: ^3.0.0 - checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e + version: 0.2.3 + resolution: "tmp@npm:0.2.3" + checksum: 73b5c96b6e52da7e104d9d44afb5d106bb1e16d9fa7d00dbeb9e6522e61b571fbdb165c756c62164be9a3bbe192b9b268c236d370a2a0955c7689cd2ae377b95 languageName: node linkType: hard @@ -18954,9 +19476,9 @@ __metadata: linkType: hard "toad-cache@npm:^3.3.0, toad-cache@npm:^3.3.1": - version: 3.4.1 - resolution: "toad-cache@npm:3.4.1" - checksum: c679bd5af6883a70a251168d05b594709b11117a9a96f040673e0b993b49f59b0e6d3fcafff50b16839658f37533a91bd9dbb72b1d34c02b0f2021c603aa7fcc + version: 3.7.0 + resolution: "toad-cache@npm:3.7.0" + checksum: d0f2092ab2c0f3355d3537c41b13888a12996f38080e6c39907e715eb382d997ccf61baab9e8eda3f202b6c07e304728106be3631c9fe3b6c001aaf15b7bdb8f languageName: node linkType: hard @@ -18982,14 +19504,14 @@ __metadata: linkType: hard "tough-cookie@npm:^4.1.3": - version: 4.1.3 - resolution: "tough-cookie@npm:4.1.3" + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" dependencies: psl: ^1.1.33 punycode: ^2.1.1 universalify: ^0.2.0 url-parse: ^1.5.3 - checksum: c9226afff36492a52118432611af083d1d8493a53ff41ec4ea48e5b583aec744b989e4280bcf476c910ec1525a89a4a0f1cae81c08b18fb2ec3a9b3a72b91dcc + checksum: 5815059f014c31179a303c673f753f7899a6fce94ac93712c88ea5f3c26e0c042b5f0c7a599a00f8e0feeca4615dba75c3dffc54f3c1a489978aa8205e09307c languageName: node linkType: hard @@ -19012,6 +19534,15 @@ __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:^5.0.0": version: 5.0.0 resolution: "tr46@npm:5.0.0" @@ -19029,9 +19560,13 @@ __metadata: linkType: hard "traverse@npm:~0.6.6": - version: 0.6.8 - resolution: "traverse@npm:0.6.8" - checksum: ef22abfc73fe2052403093b6747febbfeb52dcf827db1ca0542a78932c918706b9b12c373ef27e1c3e07e3e92eb1c646b4fe97b936fe775d59cbce7da417e13b + version: 0.6.9 + resolution: "traverse@npm:0.6.9" + dependencies: + gopd: ^1.0.1 + typedarray.prototype.slice: ^1.0.3 + which-typed-array: ^1.1.15 + checksum: e2f4b46caf849b6ea9006230995edc7376c1361f33c2110f425339a814b71b968f5c84a130ae21b4300d1849fff42cec6117c2aebde8a68d33c6871e9621a80f languageName: node linkType: hard @@ -19072,12 +19607,12 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1": - version: 1.0.3 - resolution: "ts-api-utils@npm:1.0.3" +"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0": + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" peerDependencies: typescript: ">=4.2.0" - checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 + checksum: c746ddabfdffbf16cb0b0db32bb287236a19e583057f8649ee7c49995bb776e1d3ef384685181c11a1a480369e022ca97512cb08c517b2d2bd82c83754c97012 languageName: node linkType: hard @@ -19133,17 +19668,17 @@ __metadata: languageName: node linkType: hard -"tsconfck@npm:^2.1.0": - version: 2.1.2 - resolution: "tsconfck@npm:2.1.2" +"tsconfck@npm:^3.0.3": + version: 3.1.0 + resolution: "tsconfck@npm:3.1.0" peerDependencies: - typescript: ^4.3.5 || ^5.0.0 + typescript: ^5.0.0 peerDependenciesMeta: typescript: optional: true bin: tsconfck: bin/tsconfck.js - checksum: 6fd2f7de012a724f6b4bf48ae76cc7dae2b59dd5cad2dc50bac58d224d4ed7d5c43c6b26e55d3e00636f426f8b5373c996523d73b7830d05f8479a9b83282192 + checksum: c33cb853362dc45d5efbb4763b2cd07e5808533b6c6f84dad2dcc61f3fe6d22736ec9459233f47e9e90e8c430dd4ff284d5a09e85fa63ca570b9f144a87b1c76 languageName: node linkType: hard @@ -19174,9 +19709,9 @@ __metadata: linkType: hard "tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0": - version: 2.6.2 - resolution: "tslib@npm:2.6.2" - checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad + version: 2.6.3 + resolution: "tslib@npm:2.6.3" + checksum: 74fce0e100f1ebd95b8995fbbd0e6c91bdd8f4c35c00d4da62e285a3363aaa534de40a80db30ecfd388ed7c313c42d930ee0eaf108e8114214b180eec3dbe6f5 languageName: node linkType: hard @@ -19326,7 +19861,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^3.0.0, type-fest@npm:^3.8.0": +"type-fest@npm:^3.8.0": version: 3.13.1 resolution: "type-fest@npm:3.13.1" checksum: c06b0901d54391dc46de3802375f5579868949d71f93b425ce564e19a428a0d411ae8d8cb0e300d330071d86152c3ea86e744c3f2860a42a79585b6ec2fdae8e @@ -19334,9 +19869,9 @@ __metadata: linkType: hard "type-fest@npm:^4.18.2, type-fest@npm:^4.2.0": - version: 4.18.2 - resolution: "type-fest@npm:4.18.2" - checksum: 2e9272b2b97b2f4ea2bbffda43cfce9ca89c474ad7c9565e39b80fee2ce609ea60385faffbbef98994b38feb3fa5fa38feb33acf175f4f85ee21d1773e87bf44 + version: 4.20.1 + resolution: "type-fest@npm:4.20.1" + checksum: 8cc8d86c900be4a803a4b252840b761153541f18b03c5bcc02fa2684d0237d48895cc675cd234049f110004d9ce63770242255c04890b85a133f72643c49e342 languageName: node linkType: hard @@ -19350,84 +19885,96 @@ __metadata: languageName: node linkType: hard -"type@npm:^1.0.1": - version: 1.2.0 - resolution: "type@npm:1.2.0" - checksum: dae8c64f82c648b985caf321e9dd6e8b7f4f2e2d4f846fc6fd2c8e9dc7769382d8a52369ddbaccd59aeeceb0df7f52fb339c465be5f2e543e81e810e413451ee +"type@npm:^2.7.2": + version: 2.7.3 + resolution: "type@npm:2.7.3" + checksum: 69cfda3248847998f93b9d292fd251c10facf8d29513e2047d4684509d67bae82d910d7a00c1e9d9bbf2af242d36425b6616807d6c652c5c370c2be1f0008a47 languageName: node linkType: hard -"type@npm:^2.7.2": - version: 2.7.2 - resolution: "type@npm:2.7.2" - checksum: 0f42379a8adb67fe529add238a3e3d16699d95b42d01adfe7b9a7c5da297f5c1ba93de39265ba30ffeb37dfd0afb3fb66ae09f58d6515da442219c086219f6f4 +"typed-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-typed-array: ^1.1.13 + checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-buffer@npm:1.0.0" +"typed-array-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 - is-typed-array: ^1.1.10 - checksum: 3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d languageName: node linkType: hard -"typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" +"typed-array-byte-offset@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: - call-bind: ^1.0.2 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 languageName: node linkType: hard -"typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c languageName: node linkType: hard -"typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" +"typedarray.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "typedarray.prototype.slice@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - for-each: ^0.3.3 - is-typed-array: ^1.1.9 - checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-errors: ^1.3.0 + typed-array-buffer: ^1.0.2 + typed-array-byte-offset: ^1.0.2 + checksum: 07bfebdfb7a67b2a80557bf4f1061d8a68ee847d7f04c91c7aa327aa90681f97e1ea3efef17b3b8f336a7f2da1d2ff95dd92de59a4788b4e6373318b27fca2c1 languageName: node linkType: hard -"typescript@npm:^4.6.4 || ^5.2.2, typescript@npm:^5.2.2": - version: 5.3.3 - resolution: "typescript@npm:5.3.3" +"typescript@npm:^4.6.4 || ^5.2.2, typescript@npm:^5.4.5": + version: 5.4.5 + resolution: "typescript@npm:5.4.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + checksum: 53c879c6fa1e3bcb194b274d4501ba1985894b2c2692fa079db03c5a5a7140587a1e04e1ba03184605d35f439b40192d9e138eb3279ca8eee313c081c8bcd9b0 languageName: node linkType: hard -"typescript@patch:typescript@^4.6.4 || ^5.2.2#~builtin, typescript@patch:typescript@^5.2.2#~builtin": - version: 5.3.3 - resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=14eedb" +"typescript@patch:typescript@^4.6.4 || ^5.2.2#~builtin, typescript@patch:typescript@^5.4.5#~builtin": + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#~builtin::version=5.4.5&hash=14eedb" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + checksum: 2373c693f3b328f3b2387c3efafe6d257b057a142f9a79291854b14ff4d5367d3d730810aee981726b677ae0fd8329b23309da3b6aaab8263dbdccf1da07a3ba languageName: node linkType: hard @@ -19438,7 +19985,7 @@ __metadata: languageName: node linkType: hard -"ufo@npm:^1.3.2": +"ufo@npm:^1.5.3": version: 1.5.3 resolution: "ufo@npm:1.5.3" checksum: 2f54fa543b2e689cc4ab341fe2194937afe37c5ee43cd782e6ecc184e36859e84d4197a43ae4cd6e9a56f793ca7c5b950dfff3f16fadaeef9b6b88b05c88c8ef @@ -19446,11 +19993,11 @@ __metadata: linkType: hard "uglify-js@npm:^3.1.4, uglify-js@npm:^3.5.1": - version: 3.17.4 - resolution: "uglify-js@npm:3.17.4" + version: 3.18.0 + resolution: "uglify-js@npm:3.18.0" bin: uglifyjs: bin/uglifyjs - checksum: 7b3897df38b6fc7d7d9f4dcd658599d81aa2b1fb0d074829dd4e5290f7318dbca1f4af2f45acb833b95b1fe0ed4698662ab61b87e94328eb4c0a0d3435baf924 + checksum: 887733d05d4139a94dffd04a5f07ee7d8be70201c016ea48cb82703778b5c48fadbe6e5e7ac956425522f72e657d3eade23f06ae8a0e2eeed2d684bf6cc25e36 languageName: node linkType: hard @@ -19505,9 +20052,9 @@ __metadata: react-table: ^7.8.0 shared: "workspace:*" type-fest: ^4.18.2 - typescript: ^5.2.2 + typescript: ^5.4.5 yup: ^0.32.11 - zod: 3.21.4 + zod: 3.23.8 zod-formik-adapter: ^1.3.0 languageName: unknown linkType: soft @@ -19702,7 +20249,7 @@ __metadata: languageName: node linkType: hard -"uri-js@npm:^4.2.2": +"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": version: 4.4.1 resolution: "uri-js@npm:4.4.1" dependencies: @@ -19755,9 +20302,9 @@ __metadata: languageName: node linkType: hard -"use-callback-ref@npm:^1.3.0": - version: 1.3.1 - resolution: "use-callback-ref@npm:1.3.1" +"use-callback-ref@npm:^1.3.0, use-callback-ref@npm:^1.3.2": + version: 1.3.2 + resolution: "use-callback-ref@npm:1.3.2" dependencies: tslib: ^2.0.0 peerDependencies: @@ -19766,7 +20313,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 6a6a3a8bfe88f466eab982b8a92e5da560a7127b3b38815e89bc4d195d4b33aa9a53dba50d93e8138e7502bcc7e39efe9f2735a07a673212630990c73483e8e9 + checksum: df690f2032d56aabcea0400313a04621429f45bceb4d65d38829b3680cae3856470ce72958cb7224b332189d8faef54662a283c0867dd7c769f9a5beff61787d languageName: node linkType: hard @@ -19874,11 +20421,9 @@ __metadata: linkType: hard "validate-npm-package-name@npm:^5.0.0": - version: 5.0.0 - resolution: "validate-npm-package-name@npm:5.0.0" - dependencies: - builtins: ^5.0.0 - checksum: 5342a994986199b3c28e53a8452a14b2bb5085727691ea7aa0d284a6606b127c371e0925ae99b3f1ef7cc7d2c9de75f52eb61a3d1cc45e39bca1e3a9444cbb4e + version: 5.0.1 + resolution: "validate-npm-package-name@npm:5.0.1" + checksum: 0d583a1af23aeffea7748742cf22b6802458736fb8b60323ba5949763824d46f796474b0e1b9206beb716f9d75269e19dbd7795d6b038b29d561be95dd827381 languageName: node linkType: hard @@ -19922,9 +20467,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.4.0": - version: 1.4.0 - resolution: "vite-node@npm:1.4.0" +"vite-node@npm:1.6.0": + version: 1.6.0 + resolution: "vite-node@npm:1.6.0" dependencies: cac: ^6.7.14 debug: ^4.3.4 @@ -19933,33 +20478,33 @@ __metadata: vite: ^5.0.0 bin: vite-node: vite-node.mjs - checksum: 1abbeac935a5e1e3b6161974ae28b6a3ec88766b06bc082ab3f2883345ee74f5643f3004df1c7808c2b52d445ffbd067bb79a1a3920c2eaa7ca8084b11b7de46 + checksum: ce111c5c7a4cf65b722baa15cbc065b7bfdbf1b65576dd6372995f6a72b2b93773ec5df59f6c5f08cfe1284806597b44b832efcea50d5971102428159ff4379f languageName: node linkType: hard -"vite-tsconfig-paths@npm:^4.2.1": - version: 4.2.3 - resolution: "vite-tsconfig-paths@npm:4.2.3" +"vite-tsconfig-paths@npm:^4.3.2": + version: 4.3.2 + resolution: "vite-tsconfig-paths@npm:4.3.2" dependencies: debug: ^4.1.1 globrex: ^0.1.2 - tsconfck: ^2.1.0 + tsconfck: ^3.0.3 peerDependencies: vite: "*" peerDependenciesMeta: vite: optional: true - checksum: d8a837eded390ea03c56eb97c8e35fbb8a1073c97e3c8119adab5e8c8a3f8b6dc610c5a9236c6dc3f778ea1650e72d7f5a39b82df20feec0e546f23feac74b8e + checksum: 7105ff641379f9f7055110f33067b236c8ee71b1390c0e6482412cdcc7a98c2e139c1c2a483d14fe9045d1977c14dc931e1ff302d6257ec919c70379db9d2419 languageName: node linkType: hard "vite@npm:^5.0.0": - version: 5.2.2 - resolution: "vite@npm:5.2.2" + version: 5.3.1 + resolution: "vite@npm:5.3.1" dependencies: - esbuild: ^0.20.1 + esbuild: ^0.21.3 fsevents: ~2.3.3 - postcss: ^8.4.36 + postcss: ^8.4.38 rollup: ^4.13.0 peerDependencies: "@types/node": ^18.0.0 || >=20.0.0 @@ -19989,19 +20534,19 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: ef20480a0d4145f05378d33d295917995679c75205c19872346f18ad847cca8ac90794b7cfb280f787c0db60a90afcc1ae2c2e5ccedfe4751fb4a3c0ff07be69 + checksum: a06d35566338794a877538ddacccccfdac30df7e260546dc0513e77191b86a13398b86a8082bb6c842013b0d3062f951f624a3f800867cbf06aef89e49767d6c languageName: node linkType: hard -"vitest@npm:^1.4.0": - version: 1.4.0 - resolution: "vitest@npm:1.4.0" +"vitest@npm:^1.6.0": + version: 1.6.0 + resolution: "vitest@npm:1.6.0" dependencies: - "@vitest/expect": 1.4.0 - "@vitest/runner": 1.4.0 - "@vitest/snapshot": 1.4.0 - "@vitest/spy": 1.4.0 - "@vitest/utils": 1.4.0 + "@vitest/expect": 1.6.0 + "@vitest/runner": 1.6.0 + "@vitest/snapshot": 1.6.0 + "@vitest/spy": 1.6.0 + "@vitest/utils": 1.6.0 acorn-walk: ^8.3.2 chai: ^4.3.10 debug: ^4.3.4 @@ -20013,15 +20558,15 @@ __metadata: std-env: ^3.5.0 strip-literal: ^2.0.0 tinybench: ^2.5.1 - tinypool: ^0.8.2 + tinypool: ^0.8.3 vite: ^5.0.0 - vite-node: 1.4.0 + vite-node: 1.6.0 why-is-node-running: ^2.2.2 peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 1.4.0 - "@vitest/ui": 1.4.0 + "@vitest/browser": 1.6.0 + "@vitest/ui": 1.6.0 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -20039,7 +20584,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: e7141c0ecc629c350d8c718051fb19219ca88a100d335fedbe481c4320f285380e3235316a69a330514c34663fcafa37c801151162d0a538e92821e7faad71a6 + checksum: a9b9b97e5685d630e5d8d221e6d6cd2e1e9b5b2dd61e82042839ef11549c8d2d780cf696307de406dce804bf41c1219398cb20b4df570b3b47ad1e53af6bfe51 languageName: node linkType: hard @@ -20079,16 +20624,6 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:2.4.0": - version: 2.4.0 - resolution: "watchpack@npm:2.4.0" - dependencies: - glob-to-regexp: ^0.4.1 - graceful-fs: ^4.1.2 - checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 - languageName: node - linkType: hard - "wcwidth@npm:^1.0.0, wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" @@ -20156,6 +20691,16 @@ __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:^14.0.0": version: 14.0.0 resolution: "whatwg-url@npm:14.0.0" @@ -20221,27 +20766,27 @@ __metadata: linkType: hard "which-collection@npm:^1.0.1": - version: 1.0.1 - resolution: "which-collection@npm:1.0.1" + version: 1.0.2 + resolution: "which-collection@npm:1.0.2" dependencies: - is-map: ^2.0.1 - is-set: ^2.0.1 - is-weakmap: ^2.0.1 - is-weakset: ^2.0.1 - checksum: c815bbd163107ef9cb84f135e6f34453eaf4cca994e7ba85ddb0d27cea724c623fae2a473ceccfd5549c53cc65a5d82692de418166df3f858e1e5dc60818581c + is-map: ^2.0.3 + is-set: ^2.0.3 + is-weakmap: ^2.0.2 + is-weakset: ^2.0.3 + checksum: c51821a331624c8197916598a738fc5aeb9a857f1e00d89f5e4c03dc7c60b4032822b8ec5696d28268bb83326456a8b8216344fb84270d18ff1d7628051879d9 languageName: node linkType: hard -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": - version: 1.1.13 - resolution: "which-typed-array@npm:1.1.13" +"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.4 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 + has-tostringtag: ^1.0.2 + checksum: 65227dcbfadf5677aacc43ec84356d17b5500cb8b8753059bb4397de5cd0c2de681d24e1a7bd575633f976a95f88233abfd6549c2105ef4ebd58af8aa1807c75 languageName: node linkType: hard @@ -20317,6 +20862,13 @@ __metadata: languageName: node linkType: hard +"word-wrap@npm:^1.2.5": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: f93ba3586fc181f94afdaff3a6fef27920b4b6d9eaefed0f428f8e07adea2a7f54a5f2830ce59406c8416f033f86902b91eb824072354645eea687dff3691ccb + languageName: node + linkType: hard + "word@npm:~0.3.0": version: 0.3.0 resolution: "word@npm:0.3.0" @@ -20381,9 +20933,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.14.2": - version: 8.16.0 - resolution: "ws@npm:8.16.0" +"ws@npm:^8.16.0": + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -20392,7 +20944,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b + checksum: 442badcce1f1178ec87a0b5372ae2e9771e07c4929a3180321901f226127f252441e8689d765aa5cfba5f50ac60dd830954afc5aeae81609aefa11d3ddf5cecf languageName: node linkType: hard @@ -20420,17 +20972,7 @@ __metadata: languageName: node linkType: hard -"xml2js@npm:0.5.0": - version: 0.5.0 - resolution: "xml2js@npm:0.5.0" - dependencies: - sax: ">=0.6.0" - xmlbuilder: ~11.0.0 - checksum: 1aa71d62e5bc2d89138e3929b9ea46459157727759cbc62ef99484b778641c0cd21fb637696c052d901a22f82d092a3e740a16b4ce218e81ac59b933535124ea - languageName: node - linkType: hard - -"xml2js@npm:^0.6.2": +"xml2js@npm:0.6.2, xml2js@npm:^0.6.2": version: 0.6.2 resolution: "xml2js@npm:0.6.2" dependencies: @@ -20496,14 +21038,16 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.2.2, yaml@npm:^2.3.4": - version: 2.3.4 - resolution: "yaml@npm:2.3.4" - checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 +"yaml@npm:^2.2.2, yaml@npm:^2.3.4, yaml@npm:^2.4.5": + version: 2.4.5 + resolution: "yaml@npm:2.4.5" + bin: + yaml: bin.mjs + checksum: f8efd407c07e095f00f3031108c9960b2b12971d10162b1ec19007200f6c987d2e28f73283f4731119aa610f177a3ea03d4a8fcf640600a25de1b74d00c69b3d 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.3, yargs-parser@npm:^20.2.9": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 @@ -20517,7 +21061,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.5.1": +"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.5.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: @@ -20532,21 +21076,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 - "yauzl@npm:^2.10.0": version: 2.10.0 resolution: "yauzl@npm:2.10.0" @@ -20594,13 +21123,13 @@ __metadata: linkType: hard "zod-fixture@npm:^2.5.0": - version: 2.5.1 - resolution: "zod-fixture@npm:2.5.1" + version: 2.5.2 + resolution: "zod-fixture@npm:2.5.2" dependencies: randexp: ^0.5.3 peerDependencies: zod: ">=3.0.0" - checksum: 9dc0dcf3e07b3d48f339a838e54472fd5824f92f8b66bc8f08a5063c75698b5ae22660600b8152418aaad3be65ae8f1d0fd5459ced6d4e784203e543a18db59f + checksum: fd81a294576119900ba68b6c4a94bf4a57ce85d57c30333f5b9ae8ae3a7c5bf67bc4349f131214c9666e14b0d904cdb237f80ec7282982f0226f2a25ebef1609 languageName: node linkType: hard @@ -20614,26 +21143,32 @@ __metadata: languageName: node linkType: hard -"zod-to-json-schema@npm:^3.17.1": - version: 3.22.3 - resolution: "zod-to-json-schema@npm:3.22.3" +"zod-mongodb-schema@npm:^1.0.2": + version: 1.0.2 + resolution: "zod-mongodb-schema@npm:1.0.2" + dependencies: + json-schema: ^0.4.0 + zod-to-json-schema: ^3.21.4 peerDependencies: + bson: " ^5.0.0 || ^6.0.0" zod: ^3.22.4 - checksum: 2747a3d1514f579006939c0edd6a420acae65ad016df223b09c4a542cbc8c0ae61b4d7b391228a211cde973635ed49c47b1449791982f3b32d799319bb174f42 + checksum: 63f872bfcfdaeb83061452e7137d7763a93b89a8f423a0dc2b5e904d295b7e7f3d204bec0691a0c344ef7cc1afb0a3d84a1508e66f472d16e3401f3db4f8d31f languageName: node linkType: hard -"zod@npm:3.21.4": - version: 3.21.4 - resolution: "zod@npm:3.21.4" - checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f +"zod-to-json-schema@npm:^3.21.4, zod-to-json-schema@npm:^3.23.0": + version: 3.23.1 + resolution: "zod-to-json-schema@npm:3.23.1" + peerDependencies: + zod: ^3.23.3 + checksum: bbb0fdd8d28179c912d2d1c93051e418fc933288b8ac3704e7a514498fadf7781a8417aa9d52129a6a89ed5bc5a59793d3739c4869aa38600743cb009b52856d languageName: node linkType: hard -"zod@patch:zod@npm%3A3.21.4#./.yarn/patches/zod-npm-3.21.4-9f570b215c.patch::locator=mna-lba%40workspace%3A.": - version: 3.21.4 - resolution: "zod@patch:zod@npm%3A3.21.4#./.yarn/patches/zod-npm-3.21.4-9f570b215c.patch::version=3.21.4&hash=45704f&locator=mna-lba%40workspace%3A." - checksum: 8ac3afb02adff75a1d562c3479f39331548f94cd1d7f5d52623834ec75007db83c35edd8789d47d96ccb4994eec0c0a8e0bfd17130cd1db5013fd4900e0181f5 +"zod@npm:3.23.8": + version: 3.23.8 + resolution: "zod@npm:3.23.8" + checksum: 15949ff82118f59c893dacd9d3c766d02b6fa2e71cf474d5aa888570c469dbf5446ac5ad562bb035bf7ac9650da94f290655c194f4a6de3e766f43febd432c5c languageName: node linkType: hard